为什么需要对比这两个容器引擎
Docker 在 2013 年开启了容器时代,"容器"几乎成为 Docker 的同义词。但 2018 年起,Docker 将 runC/containerd 捐赠给 CNCF 后,容器运行时走向了标准化,Podman 作为 Red Hat 主导的替代引擎迅速成熟。如今在开发机、CI 流水线、边缘设备上,"用 Docker 还是 Podman"成了一个真实的选型问题。
本文从架构、安全、兼容性、生态四个维度对比两者,并给出可落地的迁移路径。如果你刚开始接触容器,可先阅读本站的 Docker 命令速查表 与 Kubernetes 命令速查表 打基础。
一句话总结
- Docker:生态成熟、资料丰富、swarm/compose 一体化的"全家桶"
- Podman:无守护进程、原生 rootless、与 systemd 深度集成、"类 Docker 体验"的开源替代
架构:守护进程 vs 无守护进程
Docker 的 client-daemon 架构
docker CLI ──HTTP──▶ dockerd(守护进程)
│
├── containerd(容器生命周期管理)
│ └── runc(OCI 运行时)
└── 所有容器都挂在 dockerd 之下
Docker 的一切操作都经过中心化的 dockerd:
- 所有容器、网络、卷由 dockerd 统一调度
dockerd崩溃 = 所有容器失去响应(虽然容器本身不一定停)- 客户端与守护进程通过 Unix socket 通信,天然存在"本机 REST API 面"
Podman 的 daemonless 架构
podman CLI ──fork──▶ conmon(每个容器一个)
└── runc / crun(OCI 运行时)
Podman 没有中心守护进程:
- 每个容器由 CLI 直接 fork 出独立的
conmon管理进程 - 没有守护进程意味着没有单点故障
- 没有本机 REST API 面,攻击面更小
- 完全符合 Unix "每个工具只做一件事"的哲学
架构对比表
| 维度 | Docker | Podman |
|---|---|---|
| 中心守护进程 | dockerd(必须 root) | 无(daemonless) |
| 单点故障 | 有(dockerd 崩溃影响全部) | 无 |
| 本机 API 面 | /var/run/docker.sock | 无(默认) |
| 用户空间权限 | 需要 root 或 rootless 插件 | 原生支持普通用户 |
| systemd 集成 | 需要外部工具 | podman generate systemd 原生 |
安全:Rootless 是 Podman 的招牌
什么是 Rootless
Rootless(无根)容器指以普通用户身份运行容器。宿主机上不创建 root 拥有的资源,容器内进程通过 userns(用户命名空间) 映射为宿主机上的非特权用户。
攻击者即使攻破容器,获得的也是"普通用户"权限——无法直接读写宿主机的敏感文件,也无法操作宿主机系统。
两者的 Rootless 支持现状
| 能力 | Docker | Podman |
|---|---|---|
| 原生 rootless | ❌ 需安装 dockerd-rootless-setuptool.sh 插件 |
✅ 开箱即用 |
| userns 自动重映射 | 需手动配置 | 自动 |
| rootless 网络(slirp4netns) | 插件后可用 | 原生 |
| 多用户并行 | 受限(单一守护进程) | ✅ 每用户独立命名空间 |
结论:多租户 CI、共享开发机、安全敏感场景,Podman 的 rootless 是实打实的优势。
安全补充对比
- 镜像安全:两者共用 OCI 镜像格式,可用同样的镜像扫描工具(Trivy、Grype)
- 签名验证:Podman 支持
--signature-policy强制镜像签名校验;Docker 需第三方方案 - SELinux:Podman 与 Fedora/RHEL 的 SELinux 集成更好,默认生成正确的 SELinux 标签
兼容性:alias docker=podman 能行吗?
命令级兼容
绝大多数日常命令完全一致:
# 以下命令 docker/podman 通用
docker run -d --name web -p 8080:80 nginx:alpine
docker build -t myapp .
docker pull/push/exec/logs/ps/rm/stop/start/inspect
docker network create/ls/rm
docker volume create/ls/rm
很多人直接用别名切换:
alias docker=podman
不兼容的部分
| 能力 | Docker | Podman | 说明 |
|---|---|---|---|
| Docker Compose | docker compose 内置 |
需 podman-compose 或 docker-compose(v1 兼容层) |
podman-compose 覆盖大部分场景 |
| Docker Swarm | 内置 | ❌ 不支持 | 请用 Kubernetes 或 Nomad 替代 |
| Docker Desktop | 内置 GUI/虚拟机 | 需 podman machine(macOS/Windows) |
podman machine 类似但轻量 |
| BuildKit 特性 | 先进(缓存、多阶段优化) | podman build 支持 Buildah 后端 |
复杂度高的 Dockerfile 偶有差异 |
--device/GPU |
成熟 | 基本可用 | 特定驱动场景需测试 |
Dockerfile 兼容性
Podman 通过 Buildah 构建镜像,兼容标准 Dockerfile(FROM/RUN/COPY/CMD 等指令全支持)。除非你的 Dockerfile 用了很偏门的 BuildKit 特性,否则直接 podman build 即可。
Podman 的杀手锏场景
1. 与 systemd 集成
podman generate systemd 能为容器生成 systemd unit 文件,实现开机自启、崩溃自动重启、日志进 journald:
podman generate systemd --name web --files --new
# 生成 container-web.service,放入 /etc/systemd/system/
systemctl enable --now container-web
这在边缘设备、IoT、单机服务部署场景非常实用——容器像原生服务一样被管理。
2. podman play kube:本地跑生产配置
# 直接运行 Kubernetes 的 Pod YAML(不装 Kubernetes)
podman play kube deployment.yaml
开发时用生产同款 YAML 本地验证,减少"本地能跑生产不行"的落差。这也是 Kubernetes 命令速查表 推荐关注的能力。
3. 多用户/CI 场景
共享构建机或 CI Runner 上,每个用户/任务跑自己的 rootless Podman,互不干扰,无需特权。Docker 的单一守护进程在这种场景需要额外的权限管理与隔离。
迁移指南:从 Docker 到 Podman
第一步:安装
# Debian/Ubuntu
sudo apt install podman podman-compose
# Fedora/RHEL(内置)
sudo dnf install podman
# macOS/Windows
brew install podman && podman machine init && podman machine start
第二步:验证兼容性
podman version
podman ps -a
podman images
第三步:别名切换(可选)
alias docker=podman
# 写入 shell 配置
echo 'alias docker=podman' >> ~/.bashrc
第四步:处理 compose
# 方式一:podman-compose(纯 Python 实现)
podman-compose -f docker-compose.yml up -d
# 方式二:docker-compose v1(通过 podman socket 兼容层)
# podman 4.x 可启用 docker.sock 兼容端点:
systemctl --user enable --now podman.socket
export DOCKER_HOST=unix:///run/user/$(id -u)/podman/podman.sock
docker-compose up -d
迁移中的常见坑
| 坑 | 说明 | 对策 |
|---|---|---|
| rootless 端口映射 | <1024 端口(80/443)无法直接绑定 | 用 8080 等高位端口,或用 podman 的 rootful 模式 |
| 卷权限 | 容器内 UID 与宿主机不同(userns 重映射) | 用 --userns=keep-id 或调整宿主目录权限 |
| 网络性能 | rootless 走 slirp4netns,NAT 吞吐略低 | 生产网络敏感场景用 rootful + macvlan |
| 大镜像构建 | Buildah 多阶段缓存策略与 BuildKit 不同 | 优先复用 --layers,必要时保留 Docker 用于复杂构建 |
决策建议
| 你的场景 | 推荐 |
|---|---|
| 熟悉 Docker、团队资料依赖 | 继续 Docker(迁移成本 > 收益) |
| 单机服务、边缘设备、IoT | Podman(systemd 集成 + rootless) |
| 共享开发机 / CI 多租户 | Podman(每用户 rootless 隔离) |
| 安全合规敏感 | Podman(签名校验 + rootless + SELinux) |
| 生产 Kubernetes 集群 | 与本地引擎无关,运行时选 containerd/CRI-O |
| macOS/Windows 桌面开发 | 两者都可,Podman Desktop 已可用 |
一句话决策:如果你的痛点是"安全、多用户、单机服务治理",Podman 是更优解;如果团队已经在 Docker 生态里沉淀了大量 Compose 文件和经验,迁移价值有限。
容器部署配套的配置知识,可参考 Docker 命令速查表、Kubernetes 命令速查表 与 Nginx 配置速查表。需要把 docker-compose.yml 转成 Kubernetes 清单?试试本站的 docker-to-compose 工具。