Compose V2 reaches general availability as a Docker CLI plugin
The Go rewrite brings Compose into the Docker CLI and shares implementation code with it. General availability also changes the maintenance status of V1 and exposes compatibility details that command aliases cannot hide.
Compose V2 changes the implementation behind a familiar application model. A Compose file still describes the containers that make up an application, but the tool that interprets it now shares more code and packaging conventions with Docker itself. Docker declared V2 generally available on April 26, following its initial release in June 2021.
The announcement makes V2 the standard in Docker's documentation and marks V1 as deprecated. V1 will receive only high-priority security patches and critical fixes through the next milestone. The proposed end-of-life schedule remains a proposal open to feedback. General availability does not mean V1 disappears today, and it does not mean every invocation spelled docker-compose continues to run V1.
I like Docker most when a build and its surrounding environment remain legible. Compose contributes to that by putting an application's services in a file. The implementation transition matters because the same file and a familiar command can now select different execution behavior.
The language change enables shared implementation
V1 is a Python project. V2 is a rewrite in Go, distributed as a Docker CLI plugin. The V2.4.1 README, available before today's announcement, explicitly warns that installation scripts need adjustment. The normal command changes from docker-compose to docker compose.
Docker's explanation of the rewrite focuses on code reuse. Compose can use code from Moby and the Docker CLI without reimplementing equivalent behavior in Python. The announcement identifies run and exec as commands that now share code with the CLI. That reduces the number of separate implementations that must agree about terminal behavior and execution details.
Code sharing does not make the tools identical. Compose still manages an application described by services, while individual Docker commands can operate on particular containers. It does give both interfaces a common implementation for parts of that work. A fix made in a shared function can then benefit the callers that use it, instead of requiring an independently maintained translation into another language.
This is the part of the rewrite that interests me most. A change of language alone says little about user value. Reusing an existing implementation provides a concrete reason for expecting less behavioral drift between tools that perform related operations. The value depends on the actual sharing of code, which the announcement describes explicitly.
An alias preserves spelling without preserving the implementation
Docker Desktop already includes V2 in versions 3.4 and later. Since Desktop 4.4.2, the docker-compose syntax is aliased to V2 by default. A script can therefore keep the old executable spelling while running the new implementation. The General settings panel exposes the Use Docker Compose V2 setting that controls this selection.
This makes the migration easier for scripts, but it also weakens an old diagnostic shortcut. Seeing a hyphen in a command no longer establishes that the Python implementation ran. A report about a Compose problem needs to identify the implementation as well as the command spelling. Otherwise a comparison between two machines can quietly compare V1 with V2 while both reports show docker-compose up. Setup documentation should record whether Desktop supplies the command or a separate installation provides it, since that determines where its implementation comes from.
Docker permits opting out through the Desktop setting or docker-compose disable-v2. The announcement says it has no plans to remove the alias. Those are separate commitments. Retaining the old spelling as an entry point does not imply indefinite maintenance of the old Python program. The deprecation applies to that program even while an alias can keep its command syntax usable.
For Linux, the announcement describes an optional compose-plugin package associated with Moby 20.10.13. The versioned README also documents placing the downloaded binary in a CLI plugin directory, including the per-user $HOME/.docker/cli-plugins location. These installation paths differ from treating Compose as a Python package installed through pip.
BuildKit changes the default build path
V2 enables BuildKit by default. Docker names this as one of the compatibility changes that deserve attention during the transition. The announcement documents DOCKER_BUILDKIT=0 as the opt-out when the older build path is needed.
An alias cannot remove this difference because it selects the implementation that performs the build. Preserving the characters typed at the shell does not preserve the selected builder's behavior. This is why the migration deserves an explanation beyond replacing punctuation in documentation.
For a service with a build section, the Compose file is both an application description and an instruction to construct an image. A change to the default builder therefore reaches a workflow that may appear to be only starting local containers. The announcement's compatibility discussion is useful precisely because it identifies that less visible consequence.
My preference for explicit Dockerfiles makes the builder choice relevant to this release. Build reproducibility requires understanding the tools that evaluate those files. The move to V2 gives the default builder a clearer relationship with the Docker CLI, while the documented opt-out provides a way to express a different requirement during transition.
Container naming can affect external scripts
The other prominent compatibility change concerns generated container names. V2 uses hyphens between name components where V1 used underscores. A script that depends on the generated name may therefore fail even when the Compose file itself remains valid. Docker documents the --compatibility option as a mitigation.
This is a different kind of compatibility from parsing a service definition. An application description can load successfully while another script looks for a name generated by the previous implementation. That dependency sits outside the Compose file, so reading the file alone may not reveal it. The transition affects the surrounding automation as well as the tool's immediate input.
Using a project name explicitly can make an operation's scope clearer. The announcement demonstrates stopping a project through its recorded identity without needing the original Compose file in the current directory.
docker compose --project-name myproject down
Docker explains that container labels retain information about the project. The command can use that information to manage the running application. It is an example of V2 supporting operations against existing application state, which is useful when the original working directory is unavailable. It should be used with an understood project name because down changes that project's running state.
The file format and the executable evolve separately
The versioned README describes Compose files as definitions of one or more containers and shows services with a build directory, a port mapping and a mounted source directory. That application model survives the rewrite. The general availability announcement also emphasizes the Compose specification and compose-go, its Go parsing and representation library.
This separation matters for portability. A shared specification gives different implementations a way to agree about the application description. A common parser can reduce differences in how Go implementations interpret it. Neither fact guarantees identical capabilities in every target environment. Docker's announcement names integrations for Amazon ECS and Azure ACI, but a local service definition still needs to make sense for the deployment target that executes it.
The distinction also explains why V2 does not require a wholesale rewrite of application files. The central migration is the tool that interprets those files and the environment in which it runs. Compatibility work belongs where the documented differences affect a particular workflow, such as build selection or generated names.
Packaging becomes part of the maintenance argument
Docker describes static binary distribution as another benefit of the Go implementation. V1 used PyInstaller for binaries on major platforms and PyPI installation elsewhere. Python dependency combinations could therefore become part of installing the tool. V2's distribution gives the project another way to package the implementation across target architectures.
That changes what an operator needs to provision. Installing a Docker CLI plugin is a different procedure from preparing a Python dependency environment. Existing setup scripts must express the selected method accurately, particularly on machines where Desktop does not provide Compose automatically. The README's warning about installation is therefore part of the release's operational meaning, not a minor packaging footnote.
The V2.4.1 release already includes fixes involving SSH configuration during compose up builds and terminal attachment. Those details fit the architecture described in the GA announcement. Compose coordinates image construction and container interaction, so sharing Docker CLI behavior affects practical parts of the application lifecycle. General availability establishes V2 as the maintained direction for that coordination while leaving documented transition controls available to existing users.