docker-compose: command not found — the shell has no program with the hyphenated name. Compose V2 is a plugin of the Docker CLI and runs as docker compose, with a space. Type docker compose up -d instead of docker-compose up -d and the same compose file works.

docker compose version tells you whether the plugin is installed. For old scripts that hard-code the hyphen, a link to the plugin brings the name back.

The error

root@f78fbdbb1c7a:/# docker-compose up -d
bash: docker-compose: command not found

The exit code is 127. In a script or under bash -c the line reads bash: line 1: docker-compose: command not found.

Why it happens

Compose V1 was a separate program called docker-compose. Compose V2 is a CLI plugin: docker looks it up in its plugin folder when you type docker compose, and that folder is not on your PATH. The plugin's file is even named docker-compose, yet the shell cannot find a command by that name:

$ ls /usr/libexec/docker/cli-plugins/
docker-compose
docker-trust
$ type -a docker-compose; echo exit=$?
bash: line 1: type: docker-compose: not found
exit=1

So a Linux machine or WSL distribution with Docker's CLI and the Compose V2 plugin has docker compose and no docker-compose, and every tutorial, Makefile or CI step written for V1 stops at the first line. Windows hides this: Docker Desktop 4.95 ships a docker-compose.exe next to docker.exe, so on the test PC docker-compose version worked in PowerShell and in Git Bash and printed Docker Compose version v5.6.0, the same as docker compose version. Inside a WSL distribution without Docker Desktop's integration, the hyphenated name gets Docker's "could not be found in this WSL 2 distro" message instead.

The fix

Use the subcommand, with a space:

$ docker compose version
Docker Compose version 2.40.3+ds1-0ubuntu1~24.04.1

The subcommands you know keep their names: docker compose up -d, docker compose logs, docker compose down. If docker compose version fails too, the plugin itself is missing; on Ubuntu the package is docker-compose-v2.

For scripts you cannot change yet, link the plugin under the old name. Compose V2 answers to either name:

$ ln -s /usr/libexec/docker/cli-plugins/docker-compose /usr/local/bin/docker-compose; docker-compose version
Docker Compose version 2.40.3+ds1-0ubuntu1~24.04.1

The plugin path is where Ubuntu's package puts it; other packages may use another folder, so check yours before linking. Treat the link as a bridge and change the scripts to docker compose when you can.

How it was reproduced

In an ubuntu:24.04 container (Ubuntu 24.04.5 LTS) on Docker Desktop 4.95.0, with Ubuntu's own docker.io 29.1.3 and docker-compose-v2 2.40.3 packages installed by apt-get. The commands ran in bash inside the container through docker exec, as root, so the link needed no sudo; the prompt in the error block is that container's. The Windows side was checked in Windows PowerShell 5.1, Git Bash 5.2.26 and the Ubuntu-24.04 WSL distribution on the same PC. The test container was removed afterwards.

Frequently asked

What is the difference between docker-compose and docker compose?
docker-compose with a hyphen was the separate Compose V1 program. docker compose with a space is Compose V2, a plugin of the Docker CLI. The compose file stays the same, and the subcommands keep their names.
How do I fix docker-compose command not found on Ubuntu?
Run docker compose instead. If docker compose version also fails, install the Compose V2 plugin, which Ubuntu packages as docker-compose-v2. For old scripts, link the plugin binary as docker-compose.
Why does docker-compose work on Windows but not on Linux?
Docker Desktop for Windows ships a docker-compose.exe next to docker.exe, so the old name still runs. Linux packages for Compose V2 install only the CLI plugin, which answers to docker compose.

More decoded errors in the Fixes category. Compose in daily use, an app and its database from one file: Compose: The App and Its Database from One File.