Overview

Docktree runs Docker Compose services across multiple git worktrees without port conflicts.

What is Docktree?

Docktree is a CLI tool that manages Docker Compose services across multiple git worktrees simultaneously. It solves three core conflicts that arise when running multiple instances of the same project: compose project name collisions, port conflicts, and service name conflicts.

Each worktree gets its own isolated project with unique ports (allocated from range 41000–49999), container names, and volumes — all managed through generated Compose override files.

Crucially, Docktree requires zero modifications to your existing Docker Compose files. It acts as a non-intrusive, drop-in wrapper that reads your original docker-compose.yml (or compose.yml) and dynamically generates standard Compose override files on the fly, keeping your git history and compose configurations completely clean.

Why? The 5 ways Docker Compose conflicts

When you attempt to run the same Docker Compose stack across multiple git worktrees, Docker Compose will collide on several resources:

  • Project Names: By default, Compose uses the directory name as the project name. Running multiple checkouts of the same repo results in project name collisions, causing one stack to overwrite or shut down the other.
  • Host Port Bindings: If your services bind to static host ports (e.g. 8080:8080), starting a second stack will fail with a "port already allocated" error.
  • Container Names: If your compose files declare explicit container_name fields, Docker refuses to run a second container with the same name.
  • Named Volumes: Without namespace isolation, multiple instances share the same named volumes, resulting in data leakage, corruption, or database schema conflicts.
  • Default Networks: Identical project names cause Compose to use the same default network, leading to cross-network namespace pollution or connection leaks between branches.

A limited way to fix the above

To avoid the conflicts mentioned above without using Docktree, you could attempt to configure Docker Compose manually using its native features. However, this requires significant manual configuration and does not cover all conflicts cleanly:

1. Using the -p / --project-name flag

You can run docker compose -p my-branch up. This isolates project and default network namespaces.

Limitation: This does not solve host port collisions (if two stacks bind to 80:80, one will crash) or container name collisions (if you have explicit container_name fields in your YAML). It also fails to isolate external networks or named volumes unless they are also parameterized.

2. Environment Variable Interpolation

You can parameterize your docker-compose.yml by replacing hardcoded values with variables (e.g. ${PORT}, ${PROJECT_NAME}) and creating a custom .env file in each worktree directory.

Limitation: You must manually allocate and keep track of occupied host ports on your machine, and manually write them to each local .env file, which is highly error-prone.

3. Hand-written Override Files

You can manually create a docker-compose.override.yml in each worktree directory to redefine container names and ports for that specific branch.

Limitation: You have to write custom YAML overrides by hand every time you create a worktree, find available ports yourself, and clean them up afterwards.

How it works

  1. Port allocation — Each worktree gets unique ports from a managed pool. The registry prevents collisions across all worktrees in the repo.
  2. Isolation — Docktree generates a Compose override with unique project names, container names, and volumes. Shared databases get per-worktree tenant namespaces.
  3. Cleanup — When worktrees are removed or go idle, docktree clean reclaims ports and removes orphaned containers, networks, and volumes.

Getting started

Get started with Docktree by checking out the installation guide.