Docker Client Integration
Relevant source files
The following files were used as context for generating this wiki page:
The Docker Client Integration in Docktree serves as the primary bridge between the Docktree CLI and the local Docker daemon, specifically utilizing docker compose to manage isolated environments for git worktrees. Its purpose is to automate the execution of Docker commands while injecting worktree-specific context—such as unique project names and generated override files—to prevent collisions in ports, container names, and volumes.
This integration handles three primary responsibilities: lifecycle management (up, down, restart), resource cleanup for stale worktrees, and a passthrough mechanism that allows standard Docker Compose subcommands to run within Docktree's managed context.
Integration Architecture
The architecture relies on wrapping the docker and docker compose CLI commands via Go's os/exec package. Docktree calculates the necessary project isolation parameters and then delegates the actual container orchestration to Docker.
The diagram above illustrates how the Docktree CLI resolves the worktree context before invoking external Docker processes.
Sources: internal/cli/compose_passthrough.go:21-45, internal/docker/cleanup.go:94-118
Core Components
1. Compose Command Execution
Docktree executes Docker Compose commands by constructing a docker.ComposeCommand struct. This structure ensures that every call to Docker includes the -p (project name) flag and the necessary -f (file) flags for the base compose files and generated overrides.
| Field | Description |
|---|---|
ProjectName | The unique identifier for the worktree instance. |
Files | Slice of paths to compose files, including generated .override.yml. |
CommandArgs | The specific subcommand and flags (e.g., up -d). |
Sources: internal/cli/compose_passthrough.go:37-41, internal/cli/up.go:264-268
2. Resource Discovery and Labels
Docktree identifies its managed resources using Docker labels. The primary label used for filtering is docktree.managed=true.
3. Cleanup Logic
The cleanup system scans the Docker daemon for resources associated with projects that no longer have a valid worktree.
- ListDocktreeProjects: Queries
docker ps -awith a filter for thedocktree.managed=truelabel to retrieve all active project names. - ListProjectResources: Identifies containers, networks, and volumes belonging to a specific project.
- RemoveProjectResources: Executes
docker rm -f,docker network rm, anddocker volume rm -ffor the identified resources.
Sources: internal/docker/cleanup.go:20-63
Execution Flow for Passthrough Commands
When a user runs a command like docktree logs or docktree exec, the system follows a specific resolution path to ensure the command targets the correct isolated environment.
Implementation Details
Service Lifecycle Wrappers
Docktree provides native Go wrappers for standard Docker Compose lifecycle operations. These are implemented in internal/cli/compose_lifecycle.go and internal/cli/compose_passthrough.go.
// Example of a passthrough implementation
func runRestart(ctx *Context) (any, int, error) {
return runComposePassthrough(ctx, "restart", ctx.Args[1:], true, printRestartHelp)
}
Sources: internal/cli/compose_lifecycle.go:9-11
Handling Port Bind Failures
During the up command, the integration includes a retry loop to handle port collisions that might occur if a port was allocated but is actually in use by another process. If docker.IsPortBindError is detected, the registry is locked, the current allocation is released, and a new attempt is made.
Sources: internal/cli/up.go:296-312
Summary
The Docker Client Integration enables Docktree's "drop-in" functionality by transparently managing docker compose projects. By utilizing project-level isolation and label-based resource management, it ensures that developers can run multiple instances of the same service stack on a single machine without configuration conflicts.