Skip to content

Commit

Permalink
refactor(docker): use docker-compose.network.yml over default network
Browse files Browse the repository at this point in the history
  • Loading branch information
mattevans committed Jan 16, 2025
1 parent e031582 commit f11691e
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 137 deletions.
1 change: 1 addition & 0 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ archives:
- install.sh
- docker-compose.yml
- docker-compose.ports.yml
- docker-compose.network.yml

changelog:
sort: asc
Expand Down
9 changes: 9 additions & 0 deletions docker-compose.network.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
services:
sentry:
networks:
- contributoor

networks:
contributoor:
name: ${CONTRIBUTOOR_DOCKER_NETWORK}
external: true
10 changes: 1 addition & 9 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,8 @@ services:
image: ethpandaops/contributoor:${CONTRIBUTOOR_VERSION}
entrypoint: ["/usr/local/bin/sentry"]
command: ["--config=/config/config.yaml"]
networks:
- contributoor
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- ${CONTRIBUTOOR_CONFIG_PATH}/config.yaml:/config/config.yaml:ro
restart: always

networks:
contributoor:
name: ${CONTRIBUTOOR_DOCKER_NETWORK:-contributoor}
driver: bridge
external: true
restart: always
4 changes: 3 additions & 1 deletion install.bats
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ EOF
# Create compose files
touch "$CONTRIBUTOOR_PATH/releases/installer-${INSTALLER_VERSION}/docker-compose.yml"
touch "$CONTRIBUTOOR_PATH/releases/installer-${INSTALLER_VERSION}/docker-compose.ports.yml"
touch "$CONTRIBUTOOR_PATH/releases/installer-${INSTALLER_VERSION}/docker-compose.network.yml"

return 0
}
Expand All @@ -413,6 +414,7 @@ EOF
if [[ "$3" == *"/bin/contributoor" ]]; then
cp "$CONTRIBUTOOR_PATH/releases/installer-${INSTALLER_VERSION}/docker-compose.yml" "$(dirname "$3")/docker-compose.yml"
cp "$CONTRIBUTOOR_PATH/releases/installer-${INSTALLER_VERSION}/docker-compose.ports.yml" "$(dirname "$3")/docker-compose.ports.yml"
cp "$CONTRIBUTOOR_PATH/releases/installer-${INSTALLER_VERSION}/docker-compose.network.yml" "$(dirname "$3")/docker-compose.network.yml"
fi
fi
return 0
Expand All @@ -431,8 +433,8 @@ EOF
[ -f "$CONTRIBUTOOR_PATH/bin/contributoor" ]
[ -x "$CONTRIBUTOOR_PATH/bin/contributoor" ]
[ -f "$CONTRIBUTOOR_PATH/releases/installer-${INSTALLER_VERSION}/docker-compose.yml" ]
[ -f "$CONTRIBUTOOR_PATH/bin/docker-compose.yml" ]
[ -f "$CONTRIBUTOOR_PATH/releases/installer-${INSTALLER_VERSION}/docker-compose.ports.yml" ]
[ -f "$CONTRIBUTOOR_PATH/releases/installer-${INSTALLER_VERSION}/docker-compose.network.yml" ]
}

@test "setup_installer fails on checksum mismatch" {
Expand Down
5 changes: 5 additions & 0 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,11 @@ setup_installer() {
chmod 644 "$release_dir/docker-compose.ports.yml"
chmod 755 "$release_dir"
} || fail "docker-compose.ports.yml not found after extraction"

[ -f "$release_dir/docker-compose.network.yml" ] && {
chmod 644 "$release_dir/docker-compose.network.yml"
chmod 755 "$release_dir"
} || fail "docker-compose.network.yml not found after extraction"

# Create/update symlink
rm -f "$CONTRIBUTOOR_BIN/contributoor" # Remove existing symlink or file
Expand Down
215 changes: 88 additions & 127 deletions internal/sidecar/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,61 +21,75 @@ type DockerSidecar interface {

// dockerSidecar is a basic service for interacting with the docker container.
type dockerSidecar struct {
logger *logrus.Logger
composePath string
composePortsPath string
configPath string
sidecarCfg ConfigManager
installerCfg *installer.Config
logger *logrus.Logger
composePath string
composePortsPath string
composeNetworkPath string
configPath string
sidecarCfg ConfigManager
installerCfg *installer.Config
}

// NewDockerSidecar creates a new DockerSidecar.
func NewDockerSidecar(logger *logrus.Logger, sidecarCfg ConfigManager, installerCfg *installer.Config) (DockerSidecar, error) {
composePath, err := findComposeFile()
var (
composeFilename = "docker-compose.yml"
composePortsFilename = "docker-compose.ports.yml"
composeNetworkFilename = "docker-compose.network.yml"
)

composePath, err := findComposeFile(composeFilename)
if err != nil {
return nil, fmt.Errorf("failed to find %s: %w", composeFilename, err)
}

composePortsPath, err := findComposeFile(composePortsFilename)
if err != nil {
return nil, fmt.Errorf("failed to find docker-compose.yml: %w", err)
return nil, fmt.Errorf("failed to find %s: %w", composePortsFilename, err)
}

composePortsPath, err := findComposePortsFile()
composeNetworkPath, err := findComposeFile(composeNetworkFilename)
if err != nil {
return nil, fmt.Errorf("failed to find docker-compose.ports.yml: %w", err)
return nil, fmt.Errorf("failed to find %s: %w", composeNetworkFilename, err)
}

if err := validateComposePath(composePath); err != nil {
return nil, fmt.Errorf("invalid docker-compose file: %w", err)
return nil, fmt.Errorf("invalid %s file: %w", composeFilename, err)
}

if err := validateComposePath(composePortsPath); err != nil {
return nil, fmt.Errorf("invalid docker-compose.ports file: %w", err)
return nil, fmt.Errorf("invalid %s file: %w", composePortsFilename, err)
}

if err := validateComposePath(composeNetworkPath); err != nil {
return nil, fmt.Errorf("invalid %s file: %w", composeNetworkFilename, err)
}

return &dockerSidecar{
logger: logger,
composePath: filepath.Clean(composePath),
composePortsPath: filepath.Clean(composePortsPath),
configPath: sidecarCfg.GetConfigPath(),
sidecarCfg: sidecarCfg,
installerCfg: installerCfg,
logger: logger,
composePath: filepath.Clean(composePath),
composePortsPath: filepath.Clean(composePortsPath),
composeNetworkPath: filepath.Clean(composeNetworkPath),
configPath: sidecarCfg.GetConfigPath(),
sidecarCfg: sidecarCfg,
installerCfg: installerCfg,
}, nil
}

// Start starts the docker container using docker-compose.
func (s *dockerSidecar) Start() error {
// Create the network if it doesn't exist and no custom network specified. We need to do this
// because we specify 'external: true' in the docker-compose.yml file, which allows users to
// use contributoor with an existing network, but also means we need to create the network if
// it doesn't exist. If 'external: false', then the network is automatically created by compose.
if s.sidecarCfg.Get().DockerNetwork == "" {
cmd := exec.Command("docker", "network", "create", "--driver", "bridge", "contributoor")
_ = cmd.Run()
}

// If metrics are enabled, append our ports.yml as an additional -f arg.
var additionalArgs []string

if metricsHost, _ := s.sidecarCfg.Get().GetMetricsHostPort(); metricsHost != "" {
additionalArgs = append(additionalArgs, "-f", s.composePortsPath)
}

// If using a custom network, append network compose file.
if s.sidecarCfg.Get().RunMethod == config.RunMethod_RUN_METHOD_DOCKER && s.sidecarCfg.Get().DockerNetwork != "" {
additionalArgs = append(additionalArgs, "-f", s.composeNetworkPath)
}

args := append([]string{"compose", "-f", s.composePath}, additionalArgs...)
args = append(args, "up", "-d", "--pull", "always")

Expand Down Expand Up @@ -115,12 +129,6 @@ func (s *dockerSidecar) Stop() error {
return fmt.Errorf("failed to stop container: %w\nOutput: %s", err, string(output))
}

// Remove default network if we're not using a custom one
if s.sidecarCfg.Get().DockerNetwork == "" {
cmd = exec.Command("docker", "network", "rm", "contributoor")
_ = cmd.Run() // Ignore error as network might be in use by other containers
}

fmt.Printf("%sContributoor stopped successfully%s\n", tui.TerminalColorGreen, tui.TerminalColorReset)

return nil
Expand Down Expand Up @@ -193,100 +201,6 @@ func (s *dockerSidecar) updateSidecar() error {
return nil
}

// findComposeFile finds the docker-compose file based on the OS.
func findComposeFile() (string, error) {
// Get binary directory.
ex, err := os.Executable()
if err != nil {
return "", fmt.Errorf("could not get executable path: %w", err)
}

binDir := filepath.Dir(ex)

// Get the actual binary path (resolve symlink).
actualBin, err := filepath.EvalSymlinks(ex)
if err != nil {
return "", fmt.Errorf("could not resolve symlink: %w", err)
}

releaseDir := filepath.Dir(actualBin)

// First check release directory (next to actual binary).
composePath := filepath.Join(releaseDir, "docker-compose.yml")
if _, e := os.Stat(composePath); e == nil {
return composePath, nil
}

// Fallback to bin directory for backward compatibility.
if _, statErr := os.Stat(filepath.Join(binDir, "docker-compose.yml")); statErr == nil {
return filepath.Join(binDir, "docker-compose.yml"), nil
}

// Try current directory.
cwd, err := os.Getwd()
if err != nil {
return "", fmt.Errorf("could not get working directory: %w", err)
}

if _, err := os.Stat(filepath.Join(cwd, "docker-compose.yml")); err == nil {
return filepath.Join(cwd, "docker-compose.yml"), nil
}

// Try repo root
if _, err := os.Stat(filepath.Join(cwd, "..", "..", "docker-compose.yml")); err == nil {
return filepath.Join(cwd, "..", "..", "docker-compose.yml"), nil
}

return "", fmt.Errorf("docker-compose.yml not found")
}

// findComposeFile finds the docker-compose file based on the OS.
func findComposePortsFile() (string, error) {
// Get binary directory.
ex, err := os.Executable()
if err != nil {
return "", fmt.Errorf("could not get executable path: %w", err)
}

binDir := filepath.Dir(ex)

// Get the actual binary path (resolve symlink).
actualBin, err := filepath.EvalSymlinks(ex)
if err != nil {
return "", fmt.Errorf("could not resolve symlink: %w", err)
}

releaseDir := filepath.Dir(actualBin)

// First check release directory (next to actual binary).
composePath := filepath.Join(releaseDir, "docker-compose.ports.yml")
if _, e := os.Stat(composePath); e == nil {
return composePath, nil
}

// Fallback to bin directory for backward compatibility.
if _, statErr := os.Stat(filepath.Join(binDir, "docker-compose.ports.yml")); statErr == nil {
return filepath.Join(binDir, "docker-compose.ports.yml"), nil
}

// Try current directory.
cwd, err := os.Getwd()
if err != nil {
return "", fmt.Errorf("could not get working directory: %w", err)
}

if _, err := os.Stat(filepath.Join(cwd, "docker-compose.ports.yml")); err == nil {
return filepath.Join(cwd, "docker-compose.ports.yml"), nil
}

// Try repo root
if _, err := os.Stat(filepath.Join(cwd, "..", "..", "docker-compose.ports.yml")); err == nil {
return filepath.Join(cwd, "..", "..", "docker-compose.ports.yml"), nil
}

return "", fmt.Errorf("docker-compose.ports.yml not found")
}

func validateComposePath(path string) error {
// Check if path exists and is a regular file
fi, err := os.Stat(path)
Expand Down Expand Up @@ -367,3 +281,50 @@ func (s *dockerSidecar) Logs(tailLines int, follow bool) error {

return cmd.Run()
}

// findComposeFile finds the docker-compose file based on the OS.
func findComposeFile(filename string) (string, error) {
// Get binary directory.
ex, err := os.Executable()
if err != nil {
return "", fmt.Errorf("could not get executable path: %w", err)
}

binDir := filepath.Dir(ex)

// Get the actual binary path (resolve symlink).
actualBin, err := filepath.EvalSymlinks(ex)
if err != nil {
return "", fmt.Errorf("could not resolve symlink: %w", err)
}

releaseDir := filepath.Dir(actualBin)

// First check release directory (next to actual binary).
composePath := filepath.Join(releaseDir, filename)
if _, e := os.Stat(composePath); e == nil {
return composePath, nil
}

// Fallback to bin directory for backward compatibility.
if _, statErr := os.Stat(filepath.Join(binDir, filename)); statErr == nil {
return filepath.Join(binDir, filename), nil
}

// Try current directory.
cwd, err := os.Getwd()
if err != nil {
return "", fmt.Errorf("could not get working directory: %w", err)
}

if _, err := os.Stat(filepath.Join(cwd, filename)); err == nil {
return filepath.Join(cwd, filename), nil
}

// Try repo root
if _, err := os.Stat(filepath.Join(cwd, "..", "..", filename)); err == nil {
return filepath.Join(cwd, "..", "..", filename), nil
}

return "", fmt.Errorf("%s not found", filename)
}
14 changes: 14 additions & 0 deletions internal/sidecar/docker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,18 @@ services:
- "9090:9090"
`

const composeNetworkFile = `
services:
sentry:
networks:
- contributoor
networks:
contributoor:
name: ${CONTRIBUTOOR_DOCKER_NETWORK}
external: true
`

// TestDockerService_Integration tests the docker sidecar.
// We use test-containers to boot an instance of docker-in-docker.
// We can then use this to test our docker service in isolation.
Expand Down Expand Up @@ -185,6 +197,7 @@ func TestDockerService_Integration(t *testing.T) {
// Write out compose files.
require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "docker-compose.yml"), []byte(composeFile), 0644))
require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "docker-compose.ports.yml"), []byte(composePortsFile), 0644))
require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "docker-compose.network.yml"), []byte(composeNetworkFile), 0644))

require.NoError(t, ds.Start())
checkContainerHealth(t, ds)
Expand Down Expand Up @@ -267,6 +280,7 @@ func TestDockerService_Integration(t *testing.T) {
// Write out compose file
composeFilePath := filepath.Join(tmpDir, "docker-compose.yml")
require.NoError(t, os.WriteFile(composeFilePath, []byte(composeFile), 0644))
require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "docker-compose.network.yml"), []byte(composeNetworkFile), 0644))

require.NoError(t, dsCustom.Start())
checkContainerHealth(t, dsCustom)
Expand Down

0 comments on commit f11691e

Please sign in to comment.