Learn Podman - Compose & Orchestration
Series/Learn Podman/Episode 12
Episode 12 of 23

Learn Podman - Compose & Orchestration

Running existing docker-compose.yml files on top of Podman with podman-compose: understanding the manifest anatomy, Docker API compatibility, Podman Desktop integration as a GUI, and opening the Docker API socket via podman system service so docker-compatible tooling keeps working.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Introduction

In episode 11 you tidied up Podman configuration and storage: containers.conf, registries.conf, storage.conf, and an understanding of the overlayfs layout for both rootless and rootful containers. Now it's time to level up from a single container to many containers at once. Episode 12 opens the orchestration phase: running the docker-compose.yml files you already have on top of Podman, using Podman Desktop as a GUI, and exposing the Docker API socket so the Docker tooling ecosystem stays compatible.

Why Compose Still Matters in the Podman Era

Podman does solve the daemon problem, but defining dozens of containers one by one with podman run commands is impractical. Compose answers the need to declare an entire application — web, API, database, cache, worker — in a single manifest that can be reviewed, version-controlled, and reproduced in other environments.

On top of Podman there are two main paths to using the compose concept:

  • podman-compose — a utility that reads docker-compose.yml files and translates them into Podman commands.
  • Docker API socketpodman system service provides a Docker-compatible API, so tooling like docker compose and docker-py can be pointed at Podman.

Both make the move from Docker to Podman feel almost frictionless.

Anatomy of docker-compose.yml

A compose manifest is a YAML document with several top-level sections. An example three-service application:

Minimal docker-compose.yml
services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"
    depends_on:
      - api
  api:
    build: ./api
    environment:
      DB_HOST: postgres
    secrets:
      - db_password
  postgres:
    image: docker.io/library/postgres:16
    volumes:
      - pgdata:/var/lib/postgresql/data
    restart: unless-stopped
 
secrets:
  db_password:
    file: ./secrets/db_password.txt
 
volumes:
  pgdata:

The services section defines containers; volumes, networks, and secrets are shared resources referenced from services. This is what declarative means: you state what you want, not how to run it.

Compose Options and Their Podman Equivalents

Compose elementPodman equivalent
servicespodman run or a Quadlet .container unit
volumespodman volume create
networkspodman network create
portsthe -p flag on podman run
environmentthe -e flag or --env-file
restartthe --restart flag
depends_onstart order handled by podman-compose

depends_on doesn't mean "wait until the database is ready", only "start after the database has started". Healthchecks remain your responsibility at the application level.

Running Compose with podman-compose

Install podman-compose, then run it in the directory containing docker-compose.yml:

Running a stack with podman-compose
podman-compose up -d
podman-compose ps
podman-compose logs -f api
podman-compose down

podman-compose up -d reads the manifest and creates the required networks, volumes, and containers. Because it's translated into ordinary Podman commands, the resulting containers aren't managed by a daemon — you can inspect them directly with podman ps and podman inspect.

Tip

podman-compose isn't a daemon and doesn't lock the manifest. If a service needs to run manually with special flags, you can still podman run that service and let podman-compose manage the rest — there's no double-booking like on daemon-based engines.

Docker API Compatibility

The term "compatible" needs to be understood precisely. podman-compose reads the same docker-compose.yml file format, but runs it through Podman's mechanics. That means:

  • The manifest format is identical, so the same file can be used with Docker and Podman.
  • Behavior is adapted to Podman's capabilities, for example rootless port forwarding and bridge networks managed by netavark.
  • Docker-specific features (for example certain network plugins) may not be available and are skipped.

For most stacks — web plus database plus cache — this compatibility is more than enough.

Podman Desktop: A GUI for Compose

Podman Desktop is the official GUI from the Podman project. You can manage containers, pods, images, volumes, all the way to Kubernetes deployments without typing commands. For multi-container composition, Podman Desktop reads docker-compose.yml and provides a graphical view to run and monitor the stack. It's a convenient choice when onboarding team members who aren't yet familiar with the CLI.

Opening the Docker API Socket

Beyond podman-compose, Podman can speak as a Docker Engine through a compatible API endpoint. The key command:

Running the Docker API socket
podman system service --time=0 unix:///tmp/podman.sock

With --time=0 the service never times out. Now DOCKER_HOST can be pointed at that socket:

Pointing Docker tooling at Podman
export DOCKER_HOST=unix:///tmp/podman.sock
docker compose up -d

Important

By default podman system service runs in the foreground and waits on a unix socket. For production, run it as a systemd unit and restrict socket access to trusted users — this socket has the power to run containers on your behalf.

Docker-Compatible Tooling

Because the socket above serves an API compatible with Docker Engine, much of the tooling long used with Docker works directly without modification:

  • docker CLIdocker ps, docker build, docker exec.
  • docker compose — orchestration with the docker compose subcommand.
  • docker-py — a Python library for automating containers.
  • Portainer / similar UIs — monitoring panels built on the Docker API.

This practice is what earned Podman the nickname of a drop-in Docker replacement: at the protocol level, clients can't tell the difference.

Closing

In episode 12 you ran a multi-container stack on top of Podman: reading and understanding the anatomy of docker-compose.yml, translating it with podman-compose, getting to know Podman Desktop as a GUI, opening the Docker API socket with podman system service --time=0, and using docker-compatible tooling via DOCKER_HOST.

The key points to take home:

  • Compose is a manifest, not an engine — the docker-compose.yml file can be run by both Docker and Podman.
  • podman-compose translates, not mimics — containers are still managed by Podman and can be inspected with podman.
  • podman system service --time=0 opens the Docker API gateway for the entire tooling ecosystem.
  • Podman Desktop provides a graphical path to managing the same stack.

In the next episode, Episode 13, we enter the security phase: security model — how user namespaces, SELinux, AppArmor, capabilities, and seccomp work together to secure your containers. This is the layer that determines how far you're willing to run untrusted workloads.