System Architecture Overview
Relevant source files
The following files were used as context for generating this wiki page:
Docktree is a drop-in Docker Compose runner designed to solve resource collisions when running multiple git worktrees simultaneously. It provides isolation by generating project-specific overrides for host ports, container names, and volumes, ensuring that every git worktree operates within its own unique environment.
The system facilitates development by allowing AI agents and human developers to spin up isolated stacks without interfering with sibling worktrees. It achieves this through a combination of dynamic port allocation, container name stripping/rewriting, and a repo-scoped "platform" tier for shared services like databases.
Sources: README.md:1-12, internal/cli/up.go:1-20
Core Components and Project Structure
Docktree is structured as a Go CLI application with logic partitioned between the command-line interface and internal library code for Docker, Compose, and Git handling.
| Directory | Responsibility |
|---|---|
cmd/docktree/ | Entry point for the Go CLI. |
internal/cli/ | Command implementations (up, down, status, etc.) and output rendering. |
internal/compose/ | Logic for loading, synthesizing, and overriding Compose projects. |
internal/config/ | Configuration model (docktree.yml) and validation logic. |
internal/docker/ | Wrappers for Docker and Docker Compose execution and resource listing. |
internal/ports/ | Dynamic port registry and allocation logic. |
Sources: CONTRIBUTING.md:43-49, internal/cli/help_doc.go:102-137
Service Isolation and Orchestration
Docktree's primary mechanism for isolation involves intercepting a standard Docker Compose workflow and injecting dynamically generated overrides. When a user runs docktree up, the system performs several steps to ensure the resulting project is unique.
Isolation Workflow
- Identity Detection: The system identifies the repository root and the specific worktree to generate a unique
instanceName. - Port Allocation: It scans the Compose files for published ports and allocates unique host ports from a configured range (default:
41000-49999) via a port registry. - Override Generation: It creates an override YAML file that redefines
container_name,image(for built services), andports. - Volume/Network Isolation: External volumes and custom networks are namespaced with the instance name to prevent cross-worktree data leakage.
The diagram above illustrates the sequential steps Docktree takes to bring up an isolated project.
Sources: internal/cli/up.go:12-254, internal/compose/override_test.go:14-80, README.md:27-35
Shared Platform Tier
Docktree introduces a "platform" tier to optimize resource usage for services that can be shared across worktrees (e.g., a single Postgres instance hosting multiple tenant databases). This is configured via the shared.services section in docktree.yml.
Platform Synthesis
Shared services are stripped of host-port publishes and moved to a repo-scoped platform stack. Worktree services connect to these shared services via a dedicated external Docker network (docktree-platform-<repo>-net).
This diagram shows how multiple worktrees connect to a centralized platform tier using Docker DNS aliases over a shared network.
Sources: internal/compose/platform.go:70-136, internal/compose/shared_services_e2e_test.go:37-75
Tenancy Modes
Shared services support different tenancy models:
- full_share: Every worktree connects to the exact same service instance and database (default for Redis/S3).
- per_database: Every worktree gets its own logical database within a shared service (supported for Postgres/MySQL/MongoDB).
Sources: internal/config/config.go:167-175, internal/cli/init.go:210-218
Configuration and State Management
Docktree is designed to work with zero configuration but allows extensive customization via docktree.yml.
Key Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
ports.range | string | 41000-49999 | The range of host ports available for allocation. |
ports.bind_host | string | 127.0.0.1 | The host IP to bind allocated ports to. |
setup.copy | []string | [.env] | Files to copy from the main repo to worktrees during sync. |
state.directory | string | .docktree | Directory where generated overrides and instance state are stored. |
Sources: internal/config/config.go:132-159, README.md:73-90
State Tracking
Docktree tracks resources in two places:
- Local State: A
.docktree/state.jsonfile within the worktree directory containing the instance name and compose file hashes. - Global Registry: A global JSON file (typically in
XDG_CONFIG_HOME) that tracks all active instances across the machine, enabling thedocktree cleancommand to identify stale resources from deleted worktrees.
Sources: internal/cli/up.go:248-251, internal/docker/cleanup.go:25-50, tests/concurrent_smoke_test.go:94-115
Conclusion
Docktree provides a robust architectural solution for local Docker Compose orchestration in multi-worktree environments. By automating the namespacing of project resources and managing a shared platform tier, it enables seamless parallel development workflows while maintaining strict isolation and resource efficiency.