Skip to content
CAI
Software that uses CAICheck a score

docker/compose

76.6

Strong · 24 September 2026

32.3k

lines of production code

Go

primary language

5

measurements over time

CAI band scale
CAI trend line
CAI lens gauges

What this system is

This system is the Docker Compose CLI, a command-line tool for defining and running multi-container Docker applications. It manages the full lifecycle of containerized services, including building images, starting and stopping containers, and handling file synchronization for development workflows. The tool supports advanced features such as converting Compose files to Kubernetes manifests, loading stacks from remote Git or OCI sources, and integrating with Docker Desktop for enhanced observability and proxying.

How it got here

2019–2021 — Docker Compose v5 major release

15 changes.

This period centered on the major version bump to Docker Compose v5, involving a comprehensive overhaul of the build infrastructure, dependency updates to Go 1.26, and a significant refactoring of the internal API and CLI interfaces. The work introduced new features such as the attach command, bridge conversion tools, and interactive terminal navigation, while simultaneously modernizing the testing framework and removing legacy components like the TTY progress writer.

2022–2024 — remote resources, tracing, and sync improvements

12 changes.

This period focused on expanding Docker Compose's capabilities by introducing support for Git and OCI remote resources, alongside a new internal tracing infrastructure using OpenTelemetry. Significant work was also done to enhance the watch mode with a robust tar-based file sync implementation and to improve Docker Desktop integration through a dedicated client and proxy transport. Additionally, the codebase saw the removal of legacy Cucumber test infrastructure and the introduction of centralized experimental feature management.

2025–2026 — Compose transformation and reliability enhancements

10 changes.

This period focused on expanding Docker Compose capabilities through a new bridge convert command for transforming projects into other formats and a relay mechanism for proxying provider-managed services. Significant work was also dedicated to improving system reliability and developer experience, including preserving YAML formatting during transformations, ensuring strict dry-run safety, and refining OCI artifact handling with better registry compatibility and proxy support.

Features

Docker Desktop integration client and proxy transport

Added a new internal client for Docker Desktop integration that detects the active engine via the \com.docker.desktop.address\ label and communicates with the Desktop API over an in-memory socket. This includes a \BuildLogsURL\ helper to generate deep links for the Docker Desktop Logs view, pre-filtered by Compose project name, and a \ProxyTransport\ that routes OCI registry traffic through Docker Desktop's HTTP proxy. The proxy transport specifically bypasses loopback targets (localhost, 127.0.0.0/8, ::1) to allow direct connections for local registries, while ensuring that non-loopback traffic respects Docker Desktop's proxy policies rather than local environment variables.

internal/desktop · high confidence

The \compose up\ command now displays an interactive navigation menu in the terminal, allowing users to press shortcuts to view the application in Docker Desktop, open the configuration, toggle the watch mode, or detach. This menu is rendered using the new \aec\ library for ANSI control and supports OSC 8 terminal hyperlinks, making deep links to Docker Desktop logs clickable in supported terminals. Additionally, the \docker ps\ output now includes an optional \ENGINE\ column to identify the container engine, and log formatting has been modernized to use \strings.SplitSeq\ for efficiency.

cmd/formatter · high confidence

Introduce compose-relay to proxy provider-managed services

Docker Compose now deploys a lightweight network relay in place of provider-managed services, allowing project services to reach external resources (like cloud databases) using standard compose-native addresses (e.g., http://database:5432) instead of requiring injected environment variables. The relay listens on the service's declared ports and forwards traffic to the endpoints published by the provider, automatically rewriting local host addresses to the container-visible host gateway. It supports TCP with half-close propagation and reaps idle half-open connections after a grace period to prevent resource leaks.

relay · high confidence

Introduces a centralized experimental feature state management system

A new \experimental\ package has been added to manage the state of experimental features. This system allows users to globally opt out of all experimental features by setting the \COMPOSE\_EXPERIMENTAL\ environment variable. When enabled, the state can also be synchronized with Docker Desktop's feature flags, providing a unified way to control experimental capabilities within the Compose CLI.

internal/experimental · high confidence

New Git and OCI remote resource loaders with path traversal protection

Docker Compose now supports loading Compose stacks from Git repositories and OCI artifacts, enabling users to reference remote projects via \git://\ and \oci://\ URIs. This change introduces dedicated loaders that cache remote resources locally and includes strict validation to prevent path traversal attacks when resolving Git subdirectories and OCI artifact file paths. The feature is controlled by the \COMPOSE\_EXPERIMENTAL\_GIT\_REMOTE\ and \COMPOSE\_EXPERIMENTAL\_OCI\_REMOTE\ environment variables.

pkg/remote · high confidence

New \`compose attach\` command and \`compose bridge\` conversion tooling

Users can now attach to a running service's streams using the new \docker compose attach\ command, which supports options like \--index\ for multi-replica services, \--detach-keys\, \--no-stdin\, and \--sig-proxy\. Additionally, a new \docker compose bridge\ command group has been introduced to convert Compose files into other models (such as Kubernetes manifests) via the \convert\ subcommand, along with \transformations\ subcommands to list and create transformation images.

cmd/compose · high confidence

New bridge convert command for transforming Compose files

The \pkg/bridge\ package introduces a new \convert\ subcommand that transforms Docker Compose projects into other formats (such as Kubernetes) using external transformer containers. This feature includes a \CreateTransformer\ utility to extract and package transformer templates into a local Docker image, and a \Convert\ function that orchestrates the transformation by running transformer containers with the project data. To prevent accidental data loss, the output directory preparation logic now requires explicit user confirmation before wiping a non-empty directory. Additionally, the implementation handles platform-specific constraints, such as skipping the passing of user IDs on Windows where the Docker engine cannot manage them, and optimizes resource loading by skipping image pulls for build-only services.

pkg/bridge · high confidence

New internal packages for API socket passthrough, version constants, and attach logic

The \pkg/compose\ package introduces three new files to support specific engine interactions and command implementations. \apiSocket.go\ adds a mechanism to inject the Docker CLI configuration into containers that opt-in via the \use\_api\_socket\ service attribute, enabling them to communicate with the Docker Engine API directly. \api\_versions.go\ defines constants for Docker Engine API versions (1.44, 1.48, 1.49) and minimum buildx versions to gate feature availability. \attach\_service.go\ implements the \Attach\ command by delegating to the Docker CLI's \RunAttach\ function, handling detach keys and stream proxying.

pkg/compose · high confidence

New internal tracing infrastructure and memory network support

This change introduces a new internal tracing package (\internal/tracing\) that initializes OpenTelemetry providers, supports exporting spans via OTLP to both environment-configured endpoints and Docker Desktop context metadata, and provides helper functions to wrap commands in spans with detailed project, service, and container attributes (including a new project hash). It also adds a \memnet\ package to handle dialing Unix sockets and Windows named pipes, enabling the tracing client to connect to local Docker Desktop endpoints securely without TLS.

internal/tracing · high confidence

New path utility functions for child-checking and path encompassing

Added a new \internal/paths\ package providing \IsChild\ and \EncompassingPaths\ functions. \IsChild\ determines if one file path is a child of another, handling case-insensitivity and filesystem verification where necessary. \EncompassingPaths\ reduces a list of paths to the minimal set that covers all others, removing redundant sub-paths. These utilities support internal path resolution logic.

internal/paths · high confidence

New tar-based file sync implementation for watch mode

The internal sync package now includes a new tar-based syncer (internal/sync/tar.go) that copies files to containers by creating tar archives and using the Docker API's Untar endpoint, replacing previous mechanisms. This implementation supports syncing to multiple containers per service, handles file deletions when host paths disappear, and includes a retry mechanism to handle symlinked directories that previously caused sync failures. The change also introduces a shared Syncer interface and PathMapping type to standardize sync operations, and updates the underlying archive library to github.com/moby/go-archive.

internal/sync · high confidence

Support for referencing other services in build contexts

The build system now supports referencing another service's build output as a build context via the \additional\_contexts\ field in \compose.yaml\. This allows a service to depend on the result of another service's build process directly, replacing the previous method of copying artifacts using \COPY --from=base\ in the Dockerfile. The \service.dockerfile\ has been simplified to use \FROM base\ directly, and the \classic.yaml\ fixture demonstrates the standard dependency model using \depends\_on\.

pkg/e2e/fixtures/build-dependencies · high confidence

Removals

Removed legacy TTY progress writer and event types

The legacy TTY-based progress writer, along with its associated event types (Event, EventStatus) and spinner implementation, has been removed from the progress package. This change eliminates the old terminal rendering logic and its test suite, indicating a shift toward a different progress output mechanism (likely the JSON stream or other writers mentioned in the commit history) for displaying operation status to users.

pkg/progress · high confidence

API

Compose API v5: New project loading, expanded service interface, and dry-run support

The \pkg/api\ package introduces a major API evolution for Docker Compose v5. The \Service\ interface is replaced by a new \Compose\ interface that adds new commands including \Scale\, \Wait\, \Viz\, \Export\, \Commit\, \Generate\, and \Volumes\, while removing the legacy \Config\ method. Project loading is now explicit via the new \LoadProject\ method and \ProjectLoadOptions\, which allows scoping operations to specific services and registering listeners for loading events. The API also introduces a \DryRunClient\ for simulating operations without side effects, new context information via \ContextInfo\, and detailed event processing through \EventProcessor\. Additionally, the \Ports\ method now returns structured \PortPublishers\ instead of raw strings, and the \Images\ method returns a map keyed by image name.

pkg/api · high confidence

Behavioural changes

Adopts v5 module path, adds tracing and prompt backend, and updates plugin metadata

The CLI entry point now imports the \docker/compose/v5\ module instead of \v2\, reflecting the major version bump. It integrates OpenTelemetry tracing via \cmdtrace.Setup\ during command initialization and configures a pluggable user-prompt backend using \compose.WithPrompt\. The plugin metadata schema version is updated to \0.1.0\, and the User-Agent header for engine API requests is explicitly set to \compose/\<version\>\. Additionally, the hardcoded exit code for flag errors is standardized to \1\, and the \ServiceProxy\ wrapper is removed in favor of passing backend options directly to the root command.

cmd · high confidence

Display subsystem refactored with new JSON output mode and TTY renderer split

The display package has been reorganized into \cmd/display\ and split into a model/layout/screen architecture for the TTY renderer, improving testability and preventing terminal garbling. A new JSON output mode has been added, allowing users to receive machine-readable event streams. The display mode resolution is now explicit, and the dry-run prefix has been moved into the display package. The plain and quiet writers have been updated to match the new \api.EventProcessor\ interface.

cmd/display · high confidence

Docker Compose v5 release and major build system overhaul

This release marks the transition to Docker Compose v5, updating the Go package path to github.com/docker/compose/v5 and bumping the Go toolchain to version 1.26.8. The build infrastructure has been significantly restructured: the project now uses golangci-lint v2 with new formatters (gofumpt, gci) and stricter linters, and the Makefile has been updated to support parallel e2e test execution and mock validation. The Dockerfile has been modernized to use BuildKit bake for multi-platform builds, adding dedicated targets for generating and validating mocks, and introducing a new 'module' target to package the CLI as a Docker Desktop plugin. Documentation has been split into BUILDING.md and CONTRIBUTING.md, and the MAINTAINERS file has been removed in favor of external management.

(repo-wide) · high confidence

Dry-run mode now guarantees no side effects via explicit method classification

The dry-run client in \pkg/dryrun\ has been restructured to explicitly classify every Docker API method into one of three categories: read-only operations are delegated to the real daemon, mutating operations required for the workflow are faked with in-memory results, and unused mutating operations are refused with an error. This declarative approach, enforced by a new test that parses the client code, ensures that \--dry-run\ never accidentally modifies the Docker engine, addressing previous issues where the interception set was implicit and could lead to real image creation or other side effects.

pkg/dryrun · high confidence

Enhanced OpenTelemetry tracing with CLI metadata and error reporting

The command-line interface now captures richer telemetry data for every command execution. Traces include the list of flags passed to the command and whether the input terminal is a TTY, aiding in usage analysis. Additionally, command errors are now recorded as span events with the specific exit code, and OpenTelemetry shutdown errors are surfaced via the debug log level to improve observability and troubleshooting.

cmd/cmdtrace · high confidence

Enhanced Set utility and improved test assertion reliability

The Set utility in pkg/utils now includes new methods (NewSet, Has, Diff, AddAll, Remove with return value) and restores deprecated Clear and Union methods for API compatibility, while the old StringContains helper was removed. Additionally, the SafeBuffer's RequireEventuallyContains test helper has been migrated from the testify library to gotest.tools/poll, extending the default timeout to 10 seconds to better handle container startup delays on Docker Desktop.

pkg/utils · high confidence

File watch engine refactored with debouncing, improved ignore handling, and platform-specific watcher updates

The file watching engine in pkg/watch has been refactored to improve reliability and performance. A new BatchDebounceEvents mechanism groups identical file events within a 500ms sliding window to reduce redundant rebuild triggers. Dockerignore pattern matching now supports Dockerfile-specific ignore files (e.g., Dockerfile.dockerignore) and uses the standard ignorefile reader for better compatibility. The ephemeral file matcher has been expanded to ignore more IDE temp files (Kate, Go umask) and JetBrains .idea directories. Platform-specific watchers have been updated: the Darwin fsevent watcher now uses a sync.Once for idempotent closing and ignores self-events, while the naive watcher on other platforms now skips unreadable directories instead of failing the entire watch. The FileEvent type was simplified from a struct to a string, and various dependency and linting issues were resolved.

pkg/watch · high confidence

Improved process locking reliability on Windows

The internal locker mechanism now uses a dedicated PID file implementation that specifically addresses false positives on Windows. When attempting to acquire a lock, the system verifies if the process ID stored in the file actually exists using the \go-ps\ library; if the process is no longer running, the stale PID file is removed and the lock is acquired. This prevents the application from incorrectly detecting a running instance when the previous process has terminated, ensuring smoother operation for users on Windows.

internal/locker · high confidence

New internal registry credential encoding logic

A new internal registry package has been introduced to handle authentication for container registries. It provides functions to normalize registry hostnames (specifically mapping Docker Hub variants like 'docker.io' and 'registry-1.docker.io' to the canonical 'index.docker.io' key) and to encode credentials into the base64 format required by the Docker API's X-Registry-Auth header, utilizing Moby's authconfig package for the encoding process.

internal/registry · high confidence

Preserve formatting when replacing extends file and env\_file paths

The compose transform layer now replaces \extends.file\ and \extends.env\_file\ values by directly modifying the YAML source text at the specific line and column positions, rather than using a library that may alter formatting. This ensures that comments, indentation, and other stylistic details in the compose file are preserved when these paths are updated.

pkg/compose/transform · high confidence

Regenerated mocks for Moby v26, Compose v5, and updated test infrastructure

The mock implementations in \pkg/mocks\ have been regenerated to align with major dependency updates: the Docker API client now targets \github.com/moby/moby/client\ (replacing \github.com/docker/docker/client\) with updated method signatures and result types, and the Compose API mock now targets \github.com/docker/compose/v5/pkg/api\ (replacing \v2\) with a renamed \MockCompose\ type. Additionally, the test framework has migrated from the deprecated \github.com/golang/mock\ to \go.uber.org/mock\, and the \MockCli\ interface has been updated to reflect changes in the \docker/cli\ package, including the removal of deprecated methods like \Apply\ and \ContentTrustEnabled\, and the addition of OpenTelemetry-related methods such as \MeterProvider\ and \Resource\.

pkg/mocks · high confidence

Simplify internal version variable declaration

The internal package's version variable declaration has been refactored from a block-style var group to a single-line declaration. This change removes the anonymous struct syntax for the Version variable, streamlining the code without altering the runtime behavior or the injected 'dev' default value.

internal · high confidence

Updated compatibility converter for v5 and improved flag handling

The compatibility converter now targets the v5 compose plugin instead of v2, ensuring correct command translation for the upcoming major release. The argument parsing logic has been refined to properly handle string flags with equals-sign syntax (e.g., \--context=foo\) and to allow 'compose' to be used as a project name without being skipped. Additionally, the tool now correctly detects and handles missing arguments for string flags, exiting with an error rather than proceeding with incomplete input.

cmd/compatibility · high confidence

Fixes

Fix OCI artifact push fallback and blob pull routing

The internal OCI implementation now correctly handles registry compatibility and network routing: pushing Compose artifacts automatically falls back from OCI 1.1 to OCI 1.0 when a registry rejects the newer format, and pulling artifact layers fetches content directly from the blobs endpoint instead of the manifests endpoint to avoid registry errors. Additionally, OCI operations now route through a provided HTTP transport, ensuring that Docker Desktop's proxy settings are respected for both registry calls and authentication token fetches.

internal/oci · high confidence

Test coverage

Add OCI publish test fixtures for compose overrides and environment interpolation; Added e2e fixture for config hash computation; Expanded end-to-end test coverage for Compose scenarios; Expanded end-to-end test fixtures for watch actions; New declarative E2E test framework and scenario DSL; Removal of legacy Cucumber end-to-end test scenarios; Removed Cucumber test runner infrastructure; Updated e2e test fixture HTML titles.

Dependencies

Upgrade to Go 1.26 and major dependency updates

The project has upgraded its minimum Go version to 1.26.3 and updated the module path to github.com/docker/compose/v5. This change includes significant dependency updates, such as bumping the container runtime to containerd v2.3.5, the Docker CLI to v29.8.1, and the build engine to buildkit v0.33.0. Additionally, the OpenTelemetry tracing libraries have been upgraded to v1.46.0, and the compose specification parser has been updated to compose-go v2.15.1.

(dependencies) · high confidence

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

How this codebase got here

Score

  • CAI 73 → 77 (+3.6)
  • Rubric changed (rubric-2026.08.19 → rubric-2026.09.15) — scores are not directly comparable.

Lenses

  • Code Health 69 → 89 (+20.2)
  • Architecture 100 → 96 (-3.9)
  • Maturity 73 → 78 (+4.9)
  • Readiness 71 → 69 (-1.2)
  • Security 93 → 85 (-7.4)

Resolved (66)

  • Coverage not included — suite not readable by the collector
  • Dependency hygiene not measured — dependency manifest found but not parsed for hygiene
  • Duplicated block (10 lines × 2) (cmd/compose/create.go)
  • Duplicated block (10 lines × 2) (pkg/compose/pause.go)
  • Duplicated block (11 lines × 2) (cmd/compose/completion.go)
  • Duplicated block (11 lines × 2) (cmd/compose/pull.go)
  • Duplicated block (11 lines × 2) (internal/tracing/wrap.go)
  • Duplicated block (12 lines × 2) (pkg/compose/images.go)
  • Duplicated block (13 lines × 2) (pkg/compose/compose.go)
  • Duplicated block (14 lines × 2) (internal/desktop/client.go)
  • Duplicated block (14 lines × 2) (pkg/compose/cp.go)
  • Duplicated block (14 lines × 2) (pkg/compose/transform/replace.go)
  • Duplicated block (16 lines × 2) (cmd/compose/compose.go)
  • Duplicated block (7 lines × 2) (cmd/compose/attach.go)
  • Duplicated block (7 lines × 2) (cmd/compose/down.go)
  • Duplicated block (7 lines × 2) (cmd/compose/options.go)
  • Duplicated block (7 lines × 2) (pkg/compose/reconcile.go)
  • Duplicated block (9 lines × 2) (pkg/compose/observed_state.go)
  • Further sole-owners (lower concentration)
  • High CVE: [GHSA redacted] (go.mod)
  • …and 46 more

New (122)

  • ClassTooLong: reconciler (pkg/compose/reconcile.go)
  • Coverage not measured — no coverage collector is wired up
  • Dependency pinned to a stale untagged commit: github.com/acarl005/stripansi
  • Dependency pinned to a stale untagged commit: github.com/eiannone/keyboard
  • Dependency pinned to a stale untagged commit: github.com/skratchdot/open-golang
  • Dependency pinned to a stale untagged commit: github.com/tilt-dev/fsnotify
  • Documentation: hard to navigate (docs/reference/compose_run.md)
  • Documentation: no installation or build instructions (README.md)
  • Duplicated block (10 lines × 2) (pkg/compose/pause.go)
  • Duplicated block (11 lines × 2) (cmd/compose/create.go)
  • Duplicated block (12 lines × 2) (internal/tracing/wrap.go)
  • Duplicated block (12 lines × 2) (pkg/compose/down.go)
  • Duplicated block (13 lines × 2) (cmd/compose/completion.go)
  • Duplicated block (15 lines × 2) (cmd/compose/compose.go)
  • Duplicated block (15 lines × 2) (internal/desktop/client.go)
  • Duplicated block (16 lines × 2) (pkg/compose/cp.go)
  • Duplicated block (16 lines × 2) (pkg/compose/pull.go)
  • Duplicated block (16–17 lines × 2) (pkg/compose/compose.go)
  • Duplicated block (16–18 lines × 2) (pkg/compose/images.go)
  • Duplicated block (21–23 lines × 2) (cmd/compose/config.go)
  • …and 102 more

Changes since last survey

  • 251 commits — 163 feature/other, 88 fixes

By area

  • pkg/compose — 83 commits
  • pkg/e2e — 63 commits
  • (root) — 39 commits
  • cmd/compose — 19 commits
  • .github/workflows — 17 commits
  • cmd/display — 5 commits
  • docs/examples — 4 commits
  • docs/reference — 3 commits
  • pkg/api — 3 commits
  • pkg/watch — 3 commits
  • internal/oci — 2 commits
  • pkg/bridge — 2 commits
  • cmd/formatter — 1 commit
  • docs/extension.md — 1 commit
  • docs/sdk.md — 1 commit
  • internal/registry — 1 commit
  • internal/sync — 1 commit
  • internal/tracing — 1 commit
  • pkg/dryrun — 1 commit
  • pkg/remote — 1 commit

Notable commits

  • fix: build(deps): bump compose-go to the merged #14223/#931 fix
  • fix: chore(mocks): fix the stale mockgen invocation and pin its version
  • fix: e2e: fix test resource isolation and make standalone parallelism configurable
  • fix: fix(bridge): confirm before wiping non-empty convert output dir
  • fix: fix(bridge): skip pulling default image references for build-only services
  • fix: fix(bridge): validate arguments of bridge subcommands
  • fix: fix(build): TTY progress on Windows — hand the real stdout to buildkit
  • fix: fix(build): canonical content-digest producer, single image-label writer
  • fix: fix(build): hand unresolved 'auto' progress mode to bake
  • fix: fix(build): honor provenance/sbom false in per-service bake attest
  • fix: fix(build): resolve image volumes to a mountable name, not a manifest digest
  • fix: fix(compose): adapt relay/start tests to the container-spec layering
  • fix: fix(compose): move the job-target refusal into projectOrName itself
  • fix: fix(compose): reject unknown subcommands under bridge/transformations
  • fix: fix(config): resolve service environment when computing --hash
  • fix: fix(config): scan jobs in --images, --lock-image-digests, --resolve-image-digests
  • fix: fix(create, start): clear error when targeting a job by name
  • fix: fix(deps): github.com/containerd/containerd/v2 v2.3.5
  • fix: fix(deps): github.com/moby/sys/userns v0.2.1
  • fix: fix(deps): google.golang.org/grpc v1.83.2
  • …and 231 more

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

Survey your own repository

docker/compose was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.

About this page

  • The score is its most recent published measurement, taken on 24 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
  • Measured at commit c6dffb26bdfd94efb1f4e1c743f1241a150d120a — the exact code this score is about.
  • Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
  • Measured by watchdog.canine.dev using codehealth-analyzer preprod-5f8d0eb43fd7.