SSD Nodes Learn Hosting plans →
Guides Matt ConnorBy Matt Connor · Updated 2026-09-07

Is Docker Compose deprecated?

The Python docker-compose reached end of life. The docker compose plugin did not, and it still ships releases. Here is what your server actually runs.

Is Docker Compose deprecated?

Docker Compose is not deprecated. One of the two programs people call Docker Compose is: the old standalone tool, written in Python and typed as docker-compose with a hyphen, is end of life. The tool you use today is a Docker CLI plugin, typed as docker compose with a space, and it is still shipping releases. Version 5.5.1 was published on 3 September 2026 (releases page of the docker/compose repository on GitHub, checked 6 September 2026).

So the useful question is not whether Compose is dead. It is which binary your server has, and what to change in your files and your scripts. Both answers are below.

Two programs, one name

Docker's own version history page states the split. Compose v1 "was written in Python and invoked with docker-compose", while Compose v2 is "written in Go and is invoked with docker compose". The Go rewrite is a plugin for the docker CLI, so it reads the same CLI configuration and talks to the same Docker Engine. The labels are what confuse people: "V2" names the rewrite, not a version number. Docker's history page lists the supported Compose CLI versions as v2 and v5, with v5 arriving in 2025 as a functional equivalent that adds a Go SDK. A 5.x version number is still the thing everyone calls Compose V2.

One more source of confusion, worth knowing before you go looking for evidence on disk. The plugin's own file is named docker-compose. Ubuntu 24.04's docker-compose-v2 package installs exactly one program, /usr/libexec/docker/cli-plugins/docker-compose, and docker compose works because the docker CLI scans its plugin directories for files named that way. A file called docker-compose on your server proves nothing about which implementation you have.

What Docker announced about Compose V1, and when

Docker's blog post of 31 January 2023, "Docker Compose: What's New, What's Changing, What's Next", says: "Compose V1 support will no longer be provided after June 2023 and will be removed from all future Docker Desktop versions." The README on the v1 branch of the docker/compose repository is shorter: "Compose V1 is DEPRECATED", and "Since Compose V2 is now GA, Compose V1 is officially End of Life", after which only security issues were considered.

Treat that as a boundary rather than a calendar day, because that is how the sources word it. Docker wrote "after June 2023". GitHub's runner-image changelog says "Docker Compose v1 has been deprecated as of July 2023" and removed the binary from its images "effective July 9, 2024". The two sentences describe the same cutover from opposite sides of one month. The Docker documentation pages on Compose versions repeat that V1 is no longer maintained without restating a date, so if someone asks you for a source, quote the blog sentence and do not invent a precise day.

What docker-compose does on your server right now

Four things can happen when you type it. Find out which one before you change anything.

docker compose version
command -v docker-compose || echo 'no docker-compose in PATH'
readlink -f "$(command -v docker-compose)"
dpkg -S "$(command -v docker-compose)"

docker compose version printing a line like Docker Compose version v5.5.1 means the plugin is installed and the CLI can find it. That is the only result that matters for new work. The other commands tell you what the hyphenated name is bound to, if anything.

bash: docker-compose: command not found. Nothing is broken and nothing needs repair. This is the normal state of a current server whose Compose came from Ubuntu 24.04's docker-compose-v2 package, because that package installs the plugin under /usr/libexec/docker/cli-plugins/ and puts nothing in /usr/bin. Type docker compose and carry on.

It runs, and it is the current Compose. Debian 13 ships a package named docker-compose at version 2.26.1-4, and that package installs both /usr/bin/docker-compose and /usr/libexec/docker/cli-plugins/docker-compose (package file list on packages.debian.org, checked 6 September 2026). On that machine the hyphenated command is the Go implementation under the old name, because the same binary works both as a plugin and as a standalone program.

It runs, and a shim is translating it. Docker publishes a small program for this, and its README describes it like this: "Compose Switch is a replacement to the Compose V1 docker-compose (python) executable. It translates the command line into Compose V2 docker compose then run the latter." That is the wording as published in the docker/compose-switch repository. It is normally wired in with update-alternatives, so update-alternatives --display docker-compose names it. Docker Desktop offered the same idea as a setting: the 2023 blog post describes an option that "creates a symlink for you so you can continue using docker-compose to preserve your potential existing scripts, but start using the newest version of Compose". A shim keeps your old commands working, and it also means nobody on the team notices that the command changed.

It runs, and it really is the Python tool. The tell is the output of docker-compose version: V1 prints extra lines naming docker-py version: and CPython version:, because it is a Python program reporting its dependencies. Package indexes still carry it. Ubuntu 24.04's universe component has docker-compose at 1.29.2-6ubuntu1, and pip install docker-compose still resolves to 1.29.2, a release from 2021 (packages.ubuntu.com and PyPI, both checked 6 September 2026). Upstream end of life did not delete the package from anyone's index, so a server built by following an old tutorial can still land on a tool that has had no fixes for years.

Install the current Compose plugin

Docker's install page names the package docker-compose-plugin and tells you to verify with docker compose version. That package comes from Docker's own repository, not from Debian or Ubuntu, so the repository has to be configured first. The engine install, keyring and repository line included, is in the Docker Engine install for a VPS.

grep -rl download.docker.com /etc/apt/sources.list.d/
sudo apt-get update
sudo apt-get install docker-compose-plugin
docker compose version

The first line is the check that decides whether the other three will work. On a machine that followed the engine install it prints the file holding Docker's repository line, usually /etc/apt/sources.list.d/docker.list or docker.sources. On a machine that never added the repository it prints nothing, and the install then fails with E: Unable to locate package docker-compose-plugin however many times you run apt-get update, because neither Ubuntu nor Debian carries a package under that name. Add the repository first, or take the distribution package below instead.

Docker's page gives the same package name for RPM-based systems, so on Enterprise Linux 9 follow the Docker install for Rocky Linux and the plugin arrives with the engine.

If you would rather stay inside distribution packages, install docker-compose-v2 on Ubuntu 24.04 or docker-compose on Debian 13. Those are frozen at their release: Ubuntu 24.04 carries 2.24.6 and Debian 13 carries 2.26.1, while upstream is at 5.5.1 (all checked 6 September 2026). That is fine for a stable server, and it is a problem the day you need something from a later release.

Removing V1 needs one check first, because the package name means different things on different distributions. apt policy docker-compose prints the candidate version. A 1.x version is the Python tool and you can remove it. A 2.x version on Debian 13 means apt remove docker-compose would take your current Compose with it. A pip installation is invisible to apt, so uninstall that separately with pip uninstall docker-compose, or delete the virtualenv holding it.

Your compose file warns that version is obsolete

Docker's Compose file reference says the top-level version property "is defined by the Compose Specification for backward compatibility" and that "it is only informative and you'll receive a warning message that it is obsolete if used". The warning looks like this:

WARN[0000] /home/you/stack/compose.yaml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion

Delete the line. Nothing else changes, because the key had already stopped doing its old job: the same reference states that "Compose always uses the most recent schema to validate the Compose file, regardless of the version field". So version: "3.8" at the top of your file was pinning nothing, and your file was being validated against the current Compose Specification either way. Run docker compose config afterwards. That command prints the fully merged and resolved file, so you can read what Compose will actually act on.

While you are in the file, the name matters more than the deleted key. Compose looks through the working directory and its parents for compose.yaml or docker-compose.yaml, so both names work and compose.yaml is the current one. If the file itself is new ground, a first working compose.yaml on a VPS builds one up service by service, and the Compose command reference covers the daily verbs.

Scripts, systemd units and CI that call docker-compose

This is the part that actually breaks. Every place a hyphenated docker-compose is written down is a place that depends on a binary the next server you build may not have.

  • A systemd unit with ExecStart=/usr/bin/docker-compose up -d fails on a host that has only the plugin. systemctl status shows the unit failed with status=203/EXEC, which is systemd reporting that it could not execute that path. Point it at /usr/bin/docker compose up -d instead, and see starting a Compose stack at boot for a unit that survives a reboot.
  • CI images have already dropped the old binary. GitHub's changelog for hosted runners says "Docker Compose v1 has been deprecated as of July 2023" and that it would be removed "effective July 9, 2024", and it tells users to update workflow files "from using docker-compose to docker compose". A pipeline that still works because it pins an old runner image is borrowing time.
  • Unattended maintenance scripts are the quiet failure, because a broken one shows up later as a missing backup. Backing up and upgrading a Compose stack covers the order those steps need.

There are two honest ways to fix a fleet of callers. Edit them: search for docker-compose and write docker compose instead, which is the only option that leaves one command name in your runbooks. Or, where you cannot edit them (a vendor installer, a build image you do not own), put a hyphenated binary back. Docker publishes a standalone install for that case while stating that "This install scenario is not recommended and is only supported for backward compatibility purposes", and compose-switch reaches the same result by translating the command line. Both are bridges, so write down when you will remove them.

One behaviour difference bites scripts even after the command name is fixed. V1 named containers with underscores, as in myapp_db_1. The current Compose uses hyphens: myapp-db-1. A check running docker ps --filter name=myapp_db_1 now matches nothing, and a shell if that reads empty output as "nothing wrong" reports success while the service is down. Ask Compose for the name instead of guessing it: docker compose ps -q db prints the container id for that service under any naming rule. docker compose --compatibility up brings the underscores back, and Docker describes that flag as running Compose "in backward compatibility mode", so it is a migration aid and not a setting to keep.

The lifecycle verbs themselves did not change meaning between the two spellings, so the distinctions worth learning are what down removes that stop leaves alone and when a restart is not enough and you need a rebuild. Those catch far more people than the hyphen does.

Is docker the same as Docker Compose?

No, and they are not alternatives to each other. docker is the command for one container: you pass every port and volume as a flag, and your shell history is the only record of what you built. Compose reads a YAML file listing your services and the networks and volumes they use, then makes the host match that file. Both speak to the same Docker Engine over the same socket, so containers created by Compose are ordinary containers, which means docker ps lists them and docker logs reads them. Compose adds labels recording the project and service names, which is how it knows what belongs to your file. Once you run two containers that must reach each other, you want Compose. If you also want to see the state of a box in a browser, a Portainer install on a VPS shows the same containers through a web interface.

Do you need Kubernetes instead of Docker Compose?

Not on one server. Compose has no scheduler and no knowledge that other machines exist: it starts containers on the host where you run it, and if that host goes down, nothing moves anywhere. Kubernetes exists to make that decision across a group of machines, and it charges for it in a control plane and a large amount of learning. On one VPS, or two, Compose describes the whole stack in a file you can read in a minute. Move when you have a requirement you can name, such as a service that must survive a single host failing, rather than because Compose feels too simple. If your real interest is a different runtime instead of a cluster, Podman compared with Docker on a VPS covers the rootless option and how its Compose support differs.

FAQ

Is docker-compose the same as docker compose?

They started as different programs, and on some systems the hyphenated name has been repointed at the new one. docker compose with a space is the Docker CLI plugin written in Go, which is the version under active development. docker-compose with a hyphen was the Python tool that reached end of life after June 2023. That same hyphenated name is also the file name of the plugin binary, and the name Debian 13 gives its Compose v2 package, so the spelling alone tells you nothing. Run docker-compose version: a CPython version: line means you are on the old Python tool.

Do I have to delete the version line from my compose file?

You do not have to, and you should. Compose prints a warning saying the attribute version is obsolete, it will be ignored, and asking you to remove it to avoid confusion. The file works either way. Docker's file reference says Compose validates against the most recent schema regardless of that field, so the key is not selecting a file format for you and never did under Compose v2. Delete the line, then run docker compose config to confirm the file still resolves the way you expect.

Is Docker Compose still maintained in 2026?

Yes. The docker/compose repository on GitHub published version 5.5.1 on 3 September 2026, and Docker's documentation lists both Compose v2 and Compose v5 as supported CLI versions. What ended was Compose V1, the Python docker-compose program, which Docker marked as end of life on the v1 branch of that same repository. Installing the docker-compose-plugin package from Docker's repository, or your distribution's Compose v2 package, puts you on the maintained implementation.

How do I check which Compose version my server runs?

Run docker compose version first. A version line there means the plugin is installed and working. Then run command -v docker-compose followed by readlink -f "$(command -v docker-compose)". No output from the first means the hyphenated command is absent, which is expected on a current install and is not an error. A path inside a cli-plugins directory, or a link to a shim, means the old name is being served by the current Compose. Extra lines naming CPython version: in docker-compose version mean the Python V1 tool is still installed, and you can remove it once nothing calls it.