podman-compose and Docker Compose Differences
The same compose.yaml gives you `stack_web_1` from podman-compose and `stack-web-1` from `podman compose`. Underscores against hyphens, two different programs, and any script naming a container breaks when you switch.
Registries and Remote Hosts Guide 37 of 47 Intermediate
- OSUbuntu 26.04 LTS (resolute)
- Podman5.7.0
- Runtimecrun 1.21
- Networknetavark 1.16.1
- TimeAbout 12 min
- Reviewed22 August 2026
Written against the versions above. Podman follows the distribution here rather than a vendor repository, so the version you get is the one Ubuntu shipped. The commands are stable across 5.x.
| Server Name | IP Address | OS | Roles | CPU | RAM | HDD |
|---|---|---|---|---|---|---|
| PODMAN01 | 192.168.0.24 | Ubuntu 26.04 LTS | Primary Container Host | 2 Core | 4 GB | 50 GB |
Before you start
- guide 70 - the socket enabled there is what one of these two tools uses.
-
Three commands that all look like Compose
There are genuinely three things here and the names are unhelpfully similar:
podman-compose- a hyphenated Python program. It reads your compose file and issuespodmancommands. No socket involved.docker compose- the real Compose v2 fromdocker-compose-v2, talking to a Docker API. That is the previous guide.podman compose- a *space*, not a hyphen. A thin wrapper that finds whichever external provider you have and runs it.
podman-compose versionreports both podman's version and its own, which is a fair summary of what it is - a layer on top of the CLI.podman compose versionannounces the delegation explicitly:>>>> Executing external compose provider "/usr/libexec/docker/cli-plugins/docker-compose". Please see podman-compose(1) for how to disable this message. <<<<Podman is telling you it is not implementing Compose - it found Docker's binary and ran it. Note this notice is separate from the
Emulate Docker CLIone in guide 4; silencing that one with/etc/containers/nodockerleaves this one in place.bash Example session command -v podman-compose docker-compose/usr/bin/podman-composepodman-compose versionpodman version 5.7.0podman-compose version 1.5.0docker compose version>>>> Executing external compose provider "/usr/libexec/docker/cli-plugins/docker-compose". Please see podman-compose(1) for how to disable this message. <<<< Docker Compose version 2.40.3+ds1-0ubuntu1Expected result
podman-composeon the PATH, its own version output, and the external provider notice.Success conditionYou can tell the three commands apart by name.
-
The same file, two sets of names
Run
podman-compose up -don the file from the previous guide, then look at the container names:stack_web_1 docker.io/library/nginx:alpine stack_cache_1 docker.io/library/redis:alpineUnderscores, and a
_1suffix - the Compose v1 convention.Now the provider route:
stack-web-1 docker.io/library/nginx:alpine stack-cache-1 docker.io/library/redis:alpineHyphens - the v2 convention.
One compose file, two tools, two different container names. Anything that names a container breaks when you switch: a
podman execin a deploy script, a log collector's filter, a monitoring check, a colleague's runbook. And because both tools work, nothing warns you.Pick one per project and write it down. That is the practical advice, and it matters more than which one you pick.
bash Example session cd ~/stack && podman-compose up -dfc2494c69ce989ae8e96274225e18ecc27c0e260fcaffc0a8fa285dd1aa99882acf87b7385a56ecd5c15cc531752bee103a5632c4e1f063c0cd180ea845b03e9e7cbb2528c03f3b123d177865ae4d04544ca88857d90cbbe5d2897bfaba1f0e0stack_web_1stack_cache_1podman ps --format 'table {{.Names}} {{.Image}}'NAMES IMAGEstack_web_1 docker.io/library/nginx:alpinestack_cache_1 docker.io/library/redis:alpinecd ~/stack && podman-compose downstack_cache_1Error: removing container acf87b7385a56ecd5c15cc531752bee103a5632c4e1f063c0cd180ea845b03e9 network: 1 error occurred: * rootless netns: kill network process: permission denied stack_cache_1stack_web_1fc2494c69ce989ae8e96274225e18ecc27c0e260fcaffc0a8fa285dd1aa99882cd ~/stack && podman compose up -d>>>> Executing external compose provider "/usr/libexec/docker/cli-plugins/docker-compose". Please see podman-compose(1) for how to disable this message. <<<< Network stack_default Creating Network stack_default Created Container stack-web-1 Creating Container stack-cache-1 CreatingExpected resultUnderscore names from podman-compose and hyphen names from the provider.
Success conditionYou have produced two different container names from one file.
-
Which to use
The external provider (
docker composeorpodman compose) for anything real. It is the reference implementation, it tracks the Compose specification, and features land there first. If your compose file usesdepends_onconditions, healthchecks, profiles orwatch, this is the one that implements them properly.podman-composewhen you want no socket. Because it drives the CLI rather than an API, it needs nothing enabled - which suits a locked-down host, or a case where you would rather not have a Docker-compatible API listening at all. It is also pure Python and easy to read when you want to know exactly what a compose file will do.Its trade-off is coverage: it implements a large subset of the spec, and the gaps are in the newer features. When a compose file behaves oddly under it, check against the provider before debugging your file.
Worth noting both hit the rootless netns error on teardown -
podman-compose downprints it too. It is the environment, not the tool, and guide 23 is where that is pinned down.And the honest recommendation for anything unattended: neither. Compose is a development tool. A Quadlet unit (guide 40) gives you systemd's restart handling, dependency ordering and boot integration, which is what a long-running service actually needs.
bash Example session cd ~/stack && podman compose down>>>> Executing external compose provider "/usr/libexec/docker/cli-plugins/docker-compose". Please see podman-compose(1) for how to disable this message. <<<< Container stack-cache-1 Stopping Container stack-web-1 Stopping Container stack-web-1 Stopped Container stack-web-1 Removing Container stack-web-1 Removed Container stack-cache-1 Error while StoppingError response from daemon: removing container 0b1167ae05901e21ec9446e539342194a76e16a8ea7bbb5a6f1129f0fa0f231d network: 1 error occurred: * rootless netns: kill network process: permission deniedpodman ps -a --format 'table {{.Names}} {{.Status}}'NAMES STATUSstack-cache-1 Exited (0) Less than a second agoExpected resultThe stack torn down.
Success conditionYou can choose between the two and say what you gain either way.
Troubleshooting
podman-compose: command not found.Why: It is a separate package.
Fix:
sudo apt-get install -y podman-compose.podman composereports no provider found.Why: Neither
docker-composenorpodman-composeis installed for it to delegate to.Fix:Install one.
podman composeimplements nothing itself.A script that worked stopped finding its container.
Why: The compose tool changed and so did the naming convention.
Fix:
podman ps --format '{{.Names}}'for the real names. Better: give services explicitcontainer_name:values so neither tool decides.A compose feature is ignored under podman-compose.
Why: Incomplete spec coverage.
Fix:Try the same file with
docker composeto confirm the file is right before changing it.