OFFSET偏移
← 文章目录OFFSET / FIELD NOTESNO. 124

Compose provider 与 Docker 工具互操作

分开 Compose 实现、Podman wrapper 和兼容 API socket 的职责。

所在专题Podman 容器工作流 ↗
约 11 分钟阅读开始阅读

用 Docker Compose 的语法,走 Podman 的引擎。还有 VS Code Dev Container 等工具的兼容方式。


podman-compose 是什么?#

podman-compose 是一个 Python 脚本,让 Podman 也能读懂 docker-compose.yml 文件。它是单独维护的 Compose 实现;应按其版本检查 Compose 功能,而不是将它与 podman compose wrapper 混为一谈。

安装

# 可变发行版可在隔离 Python 工具环境安装;不是所有系统通用
pipx install podman-compose
# 需 Python/pipx;NixOS 用 Nix 声明包,避免绕过配置安装

# Fedora
sudo dnf install podman-compose

# Arch:先确认当前官方仓库包
sudo pacman -Syu podman-compose

基本使用

# 和 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    # 重启指定服务

示例 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 兼容:让 Docker 工具用 Podman#

很多工具(VS Code Dev Containers、Testcontainers、某些 CI)假设 Docker 的 socket 存在。Podman 可以模拟这个 socket。

启用 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 源配置

验证兼容性

# 装了 DOCKER_HOST 后
docker ps        # 实际调用的是 Podman
docker compose up # 也能用

# 如果系统还装了 docker CLI(没有 dockerd)
# docker 命令会使用 DOCKER_HOST 指向 Podman socket

VS Code Dev Containers 对接#

VS Code Dev Containers 可尝试 Podman CLI 或 Docker-compatible API;具体配置、挂载与 feature 支持需按扩展版本验证:

# 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 转发

已知问题

  • Dev Containers 的 remoteUser 字段在 rootless 模式下行为不同:容器内 root 不等于宿主机 root
  • 某些 devcontainer.json 的 mounts 语法可能需要调整路径权限
  • containerUser 与 remoteUser 应按镜像用户和 UID 映射配置;不应把设为 root 作为所有挂载错误的修复,也不能仅凭 rootless 声称无需评估风险

podman-compose 的兼容陷阱#

不支持的特性

Docker Compose 特性 podman-compose 支持? 替代方案
depends_on + condition: service_healthy 当前实现含该条件支持,依版本/用例验证 检查健康命令与实际等待行为;Quadlet需就绪通知设计
deploy.resources.limits 部分 手动 --memory --cpus 参数
secrets: 当前源码支持,来源/属性仍需核对 检查 file/environment/external 语义与权限
profiles: 当前实现支持 检查 --profile、COMPOSE_PROFILES 与目标服务展开
network_mode: host 是(rootless 下有限制) —

端口映射的差异

# Docker 中:容器可直接暴露 80 端口
# Podman rootless:是否可绑低端口取决于系统政策,示例优先高端口
ports:
  - "127.0.0.1:8080:80"   # 正确
  # - "80:80"   # 可能受系统非特权端口边界限制

卷权限问题

volumes:
  - ./data:/var/lib/mysql
  # podman rootless 下,容器内进程 UID 映射为宿主机普通用户
  # 如果数据目录属于 root,容器内可能无法写入
  # 核对应用UID映射与目录权限;当前用户拥有目录也不保证映射后的应用用户能写

什么时候用 Quadlet,什么时候用 podman-compose?#

场景 推荐工具 理由
开发环境(本地调试) podman-compose 和团队共享 docker-compose.yml,快速启停
生产服务器 Quadlet systemd 原生管理、开机自启、统一日志、自动更新
单容器服务 Quadlet 一条 .container 文件足够
临时测试/CI podman run / podman-compose 一次性任务不需要持久化配置
需要 K8s 迁移 Pod + generate kube 把 Pod 导出为 K8s YAML 上线

快捷别名设置#

以下为 Bash 示例,按配置管理方式保存;Fish 环境变量语法不同:

# 让 docker 命令实际运行 podman
alias docker=podman
alias docker-compose=podman-compose

# 需要 DOCKER_HOST 时
export DOCKER_HOST=unix:///run/user/$UID/podman/podman.sock


podman compose wrapper 与 provider 选择#

podman compose 本身不解释 Compose 规范,而是调用外部 provider 并准备连接 Podman socket 的环境。默认尝试 docker-compose 和 podman-compose,已安装的 docker-compose 优先;可在 containers.conf 的 [engine] compose_providers 或环境变量 PODMAN_COMPOSE_PROVIDER 指定路径。

# 只检查命令/版本与provider支持参数
podman compose --help
podman-compose --version
# 选择明确安装好的provider;此调用可能启动容器
PODMAN_COMPOSE_PROVIDER=/path/to/podman-compose podman compose up -d

Docker CLI 与 Podman alias 是不同方案:真正的 docker CLI 读取 DOCKER_HOST,alias docker=podman 直接调用 Podman。API 兼容不保证所有插件/工具行为相同,socket 权限也代表对应用户的容器管理能力;不要开放未经保护的 TCP API。Compose 示例密码通过受控环境提供,不能把 .env 或 secrets 文件提交仓库。depends_on 短语法不自动等待数据库就绪;两种 provider 的功能和弃用项都要按版本验证。

参考与延伸

  1. Podman 官方 run 手册 ↗
  2. Podman 官方总览与 rootless ↗
  3. Podman Compose provider 机制 ↗
  4. podman-compose 官方项目 ↗
  5. podman-compose 功能源码 ↗

根据技术笔记重新整理,示例使用通用名称。

沿专题继续阅读

Podman 容器工作流

  1. 01Podman 基础原理
  2. 02Podman 基本使用指南
  3. 03Rootless 容器,文件权限到底算谁的?
  4. 04Rootless 配置:映射、ICMP 与注册表
  5. 05Pod 体系与 Kubernetes 清单
  6. 06Quadlet 如何把容器声明变成服务?
  7. 07Quadlet 的 Pod 与多服务配置
  8. 08Compose provider 与 Docker 工具互操作
  9. 09NixOS 上的 Podman 管理
  10. 10Podman 高级运维与调优
  11. 11Docker 与 Podman:架构、兼容与共存
CONTINUE READING / 下一篇NixOS 上的 Podman 管理

通过系统模块、Home Manager 或 quadlet-nix 声明容器运行环境。