Podman Error: 'compose file not supported' Running podman-compose or docker compose
Fix Podman compose failures: enable podman.socket, set DOCKER_HOST for rootless, understand the external compose provider, unsupported keys, and move to Quadlet or kube play.
- #podman
- #containers
- #troubleshooting
- #errors
Stuck on this Podman error? Get the free incident triage checklist
A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.
Exact Error Message
$ podman compose up -d
Error: unsupported compose file version or key in ./docker-compose.yml
Error: compose file not supported
The far more common symptom of the same underlying problem is a socket failure:
$ docker compose up -d
Cannot connect to the Docker daemon at unix:///var/run/docker.sock.
Is the docker daemon running?
$ podman-compose up -d
podman-compose version: 1.x
Error: error creating container storage: cannot connect to the Podman socket
What It Means
Podman has no daemon, so “compose support” is really two separate mechanisms wearing one name. The first is podman compose, which is a thin dispatcher: it locates an external compose provider on your PATH — either podman-compose or Docker’s docker-compose v2 plugin — and hands the file to it. Podman itself does not parse the compose YAML. The second mechanism is the Podman API socket, a Docker-compatible REST endpoint that the external provider talks to instead of a Docker daemon. If that socket is not running, or the provider is not pointed at it, every compose command fails at connection time even though your YAML is perfectly valid.
That split explains the two error families. Cannot connect to the Docker daemon almost never means your compose file is wrong — it means podman.socket is not enabled or DOCKER_HOST is unset, so the client fell back to /var/run/docker.sock. A genuine compose file not supported or unknown-key error means the provider did reach Podman but the file uses schema features the provider does not implement. Rootless makes this sharper still: the socket lives under /run/user/$UID/podman/podman.sock, not the root path, and a rootless Podman cannot bind privileged ports or use host networking the way a compose file written for Docker often assumes.
Common Causes
podman.socketwas never enabled, so no API endpoint exists for the compose provider to reach.DOCKER_HOSTis unset, sending a Docker CLI or compose v2 plugin to/var/run/docker.sock.- Rootless vs root socket path confusion:
/run/user/$UID/podman/podman.sockversus/run/podman/podman.sock. - No external compose provider is installed, so
podman composehas nothing to dispatch to. - The compose file uses keys the chosen provider does not implement (Swarm
deploy,configs, somebuildextensions). - Rootless port bindings below 1024, or
network_mode: hostsemantics, behave differently than under Docker.
Diagnostic Commands
First confirm whether the socket unit exists and is listening. For rootless, everything is --user:
systemctl --user status podman.socket
ls -l /run/user/$UID/podman/podman.sock
For root-level Podman the unit and path are system-scoped:
sudo systemctl status podman.socket
ls -l /run/podman/podman.sock
Ask Podman what it thinks its remote endpoint is. podman info reports the socket path Podman advertises to clients:
podman info --format '{{.Host.RemoteSocket.Path}}'
podman info --format '{{.Host.RemoteSocket.Exists}}'
Check which compose provider podman compose will actually dispatch to, and what the environment is telling clients:
podman compose version
which podman-compose docker-compose docker
echo "DOCKER_HOST=$DOCKER_HOST"
Prove the socket answers Docker-compatible API calls directly, which isolates the socket from the provider:
curl -s --unix-socket /run/user/$UID/podman/podman.sock http://d/v1.41/_ping
curl -s --unix-socket /run/user/$UID/podman/podman.sock http://d/v1.41/version | head -c 200
If the provider connects but the file is rejected, validate the YAML schema on its own:
podman-compose -f docker-compose.yml config
Step-by-Step Resolution
- Enable and start the Podman API socket. For rootless this is a user unit:
systemctl --user enable --now podman.socket
systemctl --user status podman.socket
For root containers:
sudo systemctl enable --now podman.socket
- Point Docker-compatible clients at that socket by exporting
DOCKER_HOST. Add it to your shell profile so it survives new sessions:
export DOCKER_HOST="unix://$XDG_RUNTIME_DIR/podman/podman.sock"
echo 'export DOCKER_HOST="unix://$XDG_RUNTIME_DIR/podman/podman.sock"' >> ~/.bashrc
For root-level usage the path differs:
export DOCKER_HOST="unix:///run/podman/podman.sock"
- Make sure the socket survives logout. Rootless user units stop when your last session ends unless lingering is enabled — the same session dependency behind crun sd-bus transport endpoint:
loginctl enable-linger "$USER"
loginctl show-user "$USER" --property=Linger
- Install an actual compose provider if
podman composehas nothing to dispatch to, then confirm the dispatch:
sudo dnf install -y podman-compose # Fedora/RHEL
sudo apt install -y podman-compose # Debian/Ubuntu
podman compose version
- Remove compose keys the provider does not support. Swarm-oriented and newer schema blocks are the usual offenders:
services:
web:
image: registry.example.com/web:1.4
ports:
- "8080:8080" # rootless: use a host port >= 1024
volumes:
- webdata:/var/lib/web
# deploy: # Swarm-only; drop for Podman
# replicas: 3
volumes:
webdata:
Then bring the stack up and check it against Podman directly:
podman compose up -d
podman ps --format '{{.Names}}\t{{.Ports}}\t{{.Status}}'
- For anything long-lived, move off compose entirely. Quadlet units and
podman kube playare first-class in Podman and integrate with systemd, while compose will always be a translation layer:
# ~/.config/containers/systemd/web.container
[Container]
Image=registry.example.com/web:1.4
PublishPort=8080:8080
Volume=webdata.volume:/var/lib/web
[Install]
WantedBy=default.target
systemctl --user daemon-reload
systemctl --user start web.service
# or, from a Kubernetes-style manifest:
podman kube play deployment.yaml
For translating an existing compose file into Quadlet units or a kube manifest, the Podman prompts in the prompt library can generate a reviewed conversion.
Prevention
- Enable
podman.socketandloginctl enable-lingeras part of every host’s baseline setup, not ad hoc. - Export
DOCKER_HOSTfrom a profile file so CI shells and interactive shells agree on the endpoint. - Pin one compose provider per host and document it, rather than letting
podman composepick whatever is onPATH. - Keep compose files free of Swarm-only keys so they stay portable across providers.
- Use host ports at or above 1024 in every rootless compose file to avoid privileged-port failures.
- Treat compose as a development convenience and Quadlet or
kube playas the production deployment format.
Related Errors
Cannot connect to the Docker daemon at unix:///var/run/docker.sock—DOCKER_HOSTis unset or the socket is not enabled, not a compose file problem.short-name did not resolve to an alias— unqualified images in your compose file; see short-name did not resolve.unauthorized: authentication required— registry credentials for a compose-pulled image; see image pull unauthorized.slirp4netns failed— rootless networking failure surfacing when compose creates networks; see slirp4netns failed.
Frequently Asked Questions
Is podman compose a reimplementation of Docker Compose? No. It is a dispatcher that finds an external provider — podman-compose or Docker’s compose v2 plugin — and passes your file to it. Podman never parses the compose YAML itself, which is why provider choice changes which keys work.
Which socket path should I use, rootless or root? Rootless Podman listens on /run/user/$UID/podman/podman.sock; root Podman uses /run/podman/podman.sock. Confirm with podman info --format '{{.Host.RemoteSocket.Path}}' rather than guessing.
Why does compose work interactively but fail from cron or CI? The user socket unit stops when your login session ends. Run loginctl enable-linger $USER so the user manager and podman.socket persist without an active session.
Should I use compose at all with Podman? For local development it is fine. For anything that must survive reboots or be managed by systemd, Quadlet .container units or podman kube play are the durable path and avoid the whole socket-plus-provider chain.
Fixed it? Get 500 Podman & DevOps AI prompts — free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.
Did this fix your issue?
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.