Skip to content

Fix: improve Docker startup and compose validation#78

Draft
austin047 wants to merge 4 commits intoflatrun:mainfrom
austin047:fix/docker-startup-recommended
Draft

Fix: improve Docker startup and compose validation#78
austin047 wants to merge 4 commits intoflatrun:mainfrom
austin047:fix/docker-startup-recommended

Conversation

@austin047
Copy link

  • Set DOCKER_HOST from config to environment and verify Docker is reachable at startup
  • Update config.example deployments_path to ./deployment
  • Create deployments directory on startup if not exist; fail fast if Docker is unavailable
  • Use the Default docker_socket from the Docker client env when unset
  • Validate compose in updateDeployment via Docker Compose config
  • Add moby/moby docker client dependency for platform socket detection

@sourceant
Copy link

sourceant bot commented Feb 18, 2026

Code Review Summary

This PR improves the robustness of the Flatrun Agent by ensuring Docker is reachable at startup and adding schema validation for Docker Compose files using the CLI.

🚀 Key Improvements

  • Added moby/moby client for dynamic Docker host detection.
  • Implemented ensureDockerReachable to fail-fast if the daemon is unavailable.
  • Added comprehensive tests for Compose validation.
  • Auto-creates the deployments directory if missing.

💡 Minor Suggestions

  • Avoid using os.Setenv for DOCKER_HOST; prefer passing the socket to the client constructor.
  • Tighten permissions on temporary files used for validation.

Copy link

@sourceant sourceant bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review complete. See the overview comment for a summary.

@@ -42,6 +43,15 @@ func main() {
log.Fatalf("Failed to load config from %s: %v", resolvedConfigPath, err)
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using exec.Command("docker", "info") relies on the docker CLI being installed in the PATH. Since you've added the moby/moby client dependency, it is more efficient and reliable to check connectivity using the library's Ping() or Info() methods instead of spawning a shell process.

Suggested change
}
func ensureDockerReachable(socket string) {
ctx := context.Background()
cli, err := client.NewClientWithOpts(client.WithHost(socket), client.WithAPIVersionNegotiation())
if err != nil {
log.Fatalf("Failed to create Docker client: %v", err)
}
defer cli.Close()
if _, err := cli.Ping(ctx); err != nil {
log.Fatalf("Docker is not reachable: %v", err)
}
}

return nil
}

func validateComposeWithCLI(content string) error {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Closing the file before deleting it is safer on some operating systems (like Windows). Also, consider using defer os.Remove(tmp.Name()) immediately after creation to ensure cleanup even if subsequent steps fail.

Suggested change
func validateComposeWithCLI(content string) error {
tmp, err := os.CreateTemp("", "compose-*.yml")
if err != nil {
log.Printf("Warning: skipping CLI validation, failed to create temp file: %v", err)
return nil
}
defer os.Remove(tmp.Name())
defer tmp.Close()

@austin047 austin047 marked this pull request as draft February 18, 2026 23:42
@austin047 austin047 changed the title fix: improve Docker startup and compose validation Fix: improve Docker startup and compose validation Feb 19, 2026
@austin047 austin047 marked this pull request as ready for review February 19, 2026 00:49
Copy link

@sourceant sourceant bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review complete. See the overview comment for a summary.

log.Fatalf("Failed to load config from %s: %v", resolvedConfigPath, err)
}

os.Setenv("DOCKER_HOST", cfg.DockerSocket)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting DOCKER_HOST globally via os.Setenv can cause side effects if other parts of the application or third-party libraries expect a different environment. Since you've already added the Moby client, it is better to pass the socket explicitly to constructors rather than relying on global environment variables.

Suggested change
os.Setenv("DOCKER_HOST", cfg.DockerSocket)
ensureDockerReachable(cfg.DockerSocket)

}
if cfg.DockerSocket == "" {
cfg.DockerSocket = "unix:///var/run/docker.sock"
apiClient, err := client.New(client.FromEnv)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creating a new client just to detect the default host is slightly heavy. Note that client.FromEnv will look at the DOCKER_HOST environment variable first. Ensure this fallback logic matches the expected behavior if the agent is running inside a container.

Suggested change
apiClient, err := client.New(client.FromEnv)
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err == nil {
cfg.DockerSocket = cli.DaemonHost()
cli.Close()
} else {
cfg.DockerSocket = "unix:///var/run/docker.sock"
}

@austin047 austin047 marked this pull request as draft February 19, 2026 00:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

Comments