← 返回博客首页

Docker 与 Podman:容器引擎对比与迁移指南

为什么需要对比这两个容器引擎

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-composedocker-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 构建镜像,兼容标准 DockerfileFROM/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 工具。

广告

常见问题

Podman 是 Docker 的替代品吗?命令可以直接通用吗?

Podman 定位是 Docker 的兼容替代。绝大多数 docker 子命令(run/build/pull/exec/logs/ps 等)在 podman 下可直接使用,很多人用 `alias docker=podman` 无缝切换。差异集中在 compose(需 podman-compose 或 docker-compose)、swarm(不支持)与部分高级网络选项上。

Docker 和 Podman 的核心架构区别是什么?

Docker 使用客户端-守护进程(client-daemon)架构:所有容器由中心化的 dockerd 守护进程管理,守护进程崩溃会导致全部容器失控。Podman 采用无守护进程(daemonless)架构:每个容器由独立的 conmon 进程直接 fork 出来,无中心进程,更符合 Unix 哲学,也更容易与 systemd 集成。

Rootless 容器是什么?为什么说 Podman 更安全?

Rootless 指以普通用户身份运行容器,容器内进程映射到宿主机的非特权用户(userns 用户命名空间重映射)。Podman 原生支持 rootless,无需额外配置;Docker 需要额外安装 rootless 插件且体验不完整。rootless 模式下容器即使被攻破,攻击者拿到的也是普通用户权限,横向提权面大幅缩小。

Kubernetes 场景下选 Docker 还是 Podman?

Kubernetes 1.24 起已移除 dockershim,Kubelet 通过 CRI 直接与 containerd 等运行时通信,不再需要 Docker。Podman 的优势在开发与单机场景:`podman play kube` 能直接把 Kubernetes Pod YAML 在本地跑起来,无缝对齐生产配置。生产集群的运行时选型(containerd/CRI-O)与本地用 Docker 还是 Podman 是两回事。

← 返回博客首页