Use Docker Compose syntax with the Podman engine, and connect tools such as VS Code Dev Containers.
What Is podman-compose?#
podman-compose is a Python script that lets Podman read docker-compose.yml files. It is a separately maintained Compose implementation. Check Compose feature support for its specific version rather than confusing it with the podman compose wrapper.
Installation
# 可变发行版可在隔离 Python 工具环境安装;不是所有系统通用
pipx install podman-compose
# 需 Python/pipx;NixOS 用 Nix 声明包,避免绕过配置安装
# Fedora
sudo dnf install podman-compose
# Arch:先确认当前官方仓库包
sudo pacman -Syu podman-composeBasic Usage
# 和 docker-compose 命令几乎一样,把 docker 换成 podman
podman-compose up -d # 启动所有服务(后台)
podman-compose ps # 查看服务状态
podman-compose logs -f # 跟踪日志
podman-compose stop # 停止所有服务
podman-compose down # 停止并删除容器、网络
podman-compose down -v # 同时删除卷(数据丢失!)
podman-compose restart web # 重启指定服务Example docker-compose.yml
services:
db:
image: docker.io/library/postgres:16-alpine
environment:
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD:?provide a non-public password}"
volumes:
- pgdata:/var/lib/postgresql/data
restart: always
web:
image: docker.io/library/nginx:alpine
ports:
- "127.0.0.1:8080:80"
depends_on:
- db
volumes:
pgdata:podman-compose up -d
# 效果和 docker-compose up -d 几乎一样Docker Socket Compatibility: Use Docker Tools with Podman#
Many tools, including VS Code Dev Containers, Testcontainers, and some CI systems, assume a Docker socket exists. Podman can emulate this socket.
Enable the Podman Socket
# 启动用户级 Docker 兼容 socket
systemctl --user enable --now podman.socket
# 设置环境变量,让 Docker 客户端连接到 Podman 的 socket
export DOCKER_HOST=unix:///run/user/$(id -u)/podman/podman.sock
# 把这个写入 shell 配置文件以便永久生效
# Bash 中可将上述 export 按配置管理方式保存;NixOS/Home Manager 写 Nix 源配置Verify Compatibility
# 装了 DOCKER_HOST 后
docker ps # 实际调用的是 Podman
docker compose up # 也能用
# 如果系统还装了 docker CLI(没有 dockerd)
# docker 命令会使用 DOCKER_HOST 指向 Podman socketConnect VS Code Dev Containers#
With VS Code Dev Containers, you can try the Podman CLI or the Docker-compatible API. Verify the configuration, mounts, and feature support against your extension version:
# 1. 启用 podman socket
systemctl --user enable --now podman.socket
# 2. 设置环境变量
export DOCKER_HOST=unix:///run/user/$UID/podman/podman.sock
# 3. 在 VS Code 设置中
# "dev.containers.dockerPath": "podman"
# 或者直接用 Docker 路径,通过 DOCKER_HOST 转发Known Issues
- The Dev Containers
remoteUserfield behaves differently in rootless mode: root inside a container is not root on the host - In some
devcontainer.jsonfiles, themountssyntax may require adjustments to path permissions - Configure
containerUserandremoteUseraccording to the image's users and UID mappings. Setting them to root is not a universal fix for mount errors, and rootless mode alone does not eliminate the need to assess risk
podman-compose Compatibility Pitfalls#
Unsupported Features
| Docker Compose Feature | Supported by podman-compose? | Alternative |
|---|---|---|
depends_on + condition: service_healthy |
The current implementation supports this condition; verify your version and use case | Check the health command and actual waiting behavior; Quadlet requires a readiness-notification design |
deploy.resources.limits |
Partial | Explicit --memory and --cpus arguments |
secrets: |
Supported in the current source; still verify sources and attributes | Check file/environment/external semantics and permissions |
profiles: |
Supported by the current implementation | Check --profile, COMPOSE_PROFILES, and expansion of the selected services |
network_mode: host |
Yes (with limitations in rootless mode) | — |
Port-mapping Differences
# Docker 中:容器可直接暴露 80 端口
# Podman rootless:是否可绑低端口取决于系统政策,示例优先高端口
ports:
- "127.0.0.1:8080:80" # 正确
# - "80:80" # 可能受系统非特权端口边界限制Volume Permission Issues
volumes:
- ./data:/var/lib/mysql
# podman rootless 下,容器内进程 UID 映射为宿主机普通用户
# 如果数据目录属于 root,容器内可能无法写入
# 核对应用UID映射与目录权限;当前用户拥有目录也不保证映射后的应用用户能写When Should You Use Quadlet or podman-compose?#
| Scenario | Recommended Tool | Reason |
|---|---|---|
| Development environment (local debugging) | podman-compose | Share docker-compose.yml with the team and start or stop services quickly |
| Production server | Quadlet | Native systemd management, startup at boot, unified logs, and automatic updates |
| Single-container service | Quadlet | One .container file is enough |
| Temporary tests/CI | podman run / podman-compose | One-off tasks do not need persistent configuration |
| Migration to K8s required | Pod + generate kube | Export the Pod as K8s YAML for deployment |
Convenient Aliases#
The following examples use Bash; save them through your configuration-management workflow. Fish uses different environment-variable syntax:
# 让 docker 命令实际运行 podman
alias docker=podman
alias docker-compose=podman-compose
# 需要 DOCKER_HOST 时
export DOCKER_HOST=unix:///run/user/$UID/podman/podman.sockThe podman compose Wrapper and Provider Selection#
podman compose does not interpret the Compose specification itself. It calls an external provider and prepares the environment for connecting to the Podman socket. By default it tries docker-compose and podman-compose, giving an installed docker-compose priority. You can specify a path through [engine] compose_providers in containers.conf or the PODMAN_COMPOSE_PROVIDER environment variable.
# 只检查命令/版本与provider支持参数
podman compose --help
podman-compose --version
# 选择明确安装好的provider;此调用可能启动容器
PODMAN_COMPOSE_PROVIDER=/path/to/podman-compose podman compose up -dThe Docker CLI and a Podman alias are different approaches: the real docker CLI reads DOCKER_HOST, while alias docker=podman invokes Podman directly. API compatibility does not guarantee identical behavior across all plugins and tools. Socket permissions also grant the corresponding user's container-management capabilities; do not expose an unprotected TCP API. Supply passwords for the Compose examples through a controlled environment, and never commit .env or secrets files to the repository. The short syntax for depends_on does not automatically wait for the database to be ready. Verify both providers' features and deprecations against their versions.
References & further reading
- Official Podman run Manual ↗
- Official Podman Overview and Rootless Mode ↗
- Podman Compose Provider Mechanism ↗
- Official podman-compose Project ↗
- podman-compose Feature Source Code ↗
Adapted from technical notes. Examples use generic names.
Continue along a reading path
Podman container workflows
- 01Podman fundamentals
- 02A basic Podman usage guide
- 03Rootless containers: whose file permissions count?
- 04Rootless configuration: mappings, ICMP, and registries
- 05Pods and Kubernetes manifests
- 06How does Quadlet turn container declarations into services?
- 07Pods and multi-service configuration with Quadlet
- 08Compose providers and interoperability with Docker tools
- 09Managing Podman on NixOS
- 10Advanced Podman operations and tuning
- 11Docker and Podman: architecture, compatibility, and coexistence