项目地址:https://github.com/containers/podman 定位:Docker 的替代者——无 daemon、无 root、镜像兼容 OCI,Red Hat 主导,RHEL 系默认容器工具。
| 元信息 | 说明 |
|---|---|
| 语言 | Go |
| 星标 | 24k+ ⭐ |
| 协议 | Apache 2.0 |
| CLI 兼容 | alias docker=podman 大部分命令直接可用 |
| 生态 | Buildah(构建)/ Skopeo(镜像搬运)/ Podman Desktop |
1、背景:Docker daemon 的三宗罪
Docker 架构:docker CLI → dockerd(root 权限守护进程)→ containerd → runc。这个 daemon 模式在生产与安全视角有三个先天问题:
① 单点:daemon 挂了/升级,所有容器陪葬(容器生命周期与 daemon 绑定)
② 提权:daemon 以 root 运行,docker 组成员 ≈ 免密 sudo
(历史上多次 CVE 都源于此:容器逃逸 → root → 宿主沦陷)
③ 多租户:所有用户共享一个 daemon,谁都能看/停别人的容器
Podman 的答案:fork-exec 模型——podman run 直接 fork 出容器进程(conmon 监控),没有中间 daemon。容器是普通子进程:daemon 不存在,上述三个问题从架构上消失。
2、核心设计对比
2.1、架构差异图
Docker: docker CLI ──unix socket──> dockerd(root) ──> containerd ──> runc
│ 所有用户共享、root 权限
Podman: podman run(用户 A)──fork/exec──> conmon ──> runc ← 容器=A 的子进程
podman run(用户 B)──fork/exec──> conmon ──> runc ← 容器=B 的子进程
(每个用户独立的容器存储与配置,天然隔离)
连带收益:
- rootless 模式:普通用户用 user namespace(subuid/subgid 映射)跑容器,容器内 root 映射为宿主普通用户——逃逸了也只是个普通账号;
- systemd 原生集成:
podman generate systemd/ Quadlet(*.container文件)把容器交给 systemd 管理——开机自启、依赖关系、日志全走操作系统原语,不需要--restart=always这类 daemon 层重造轮子。
2.2、Pod:Podman 的名字来源
与 Docker 单容器不同,Podman 原生支持 pod 概念(借自 K8s):多个容器共享 network namespace(localhost 互通)、PID 等:
podman pod create --name web -p 8080:80
podman run -d --pod web nginx # web 服务
podman run -d --pod web redis # 同 pod,nginx 可用 localhost:6379 连
podman generate kube web -f web.yaml # 直接导出 K8s YAML!
podman generate kube 是学习 K8s 的脚手架:本地用 pod 跑通的组合,导出 YAML 稍改就能上集群——本地容器与 K8s 工作负载之间的翻译层。
3、快速上手
# 安装(各大发行版均有包)
sudo apt install podman # Debian/Ubuntu
brew install podman # macOS(需 VM:podman machine init && podman machine start)
# 无缝迁移:CLI 几乎同 docker
podman pull docker.io/library/nginx:alpine
podman run -d -p 8080:80 --name web nginx:alpine
podman ps; podman logs -f web
alias docker=podman # 肌肉记忆保留
# rootless 验证(普通用户即可,无需 sudo)
whoami # → dev
podman run alpine whoami # → root(容器内),宿主上是 dev(userns 映射)
ls ~/.local/share/containers/storage # 容器数据在用户家目录
Quadlet 开机自启(推荐方式,替代 docker restart 策略):
# /etc/containers/systemd/web.container
[Container]
Image=docker.io/library/nginx:alpine
PublishPort=8080:80
[Service]
Restart=always
[Install]
WantedBy=multi-user.target
# systemctl daemon-reload && systemctl start web.service
4、生产实践视角
- CI/CD 构建镜像:
podman build兼容 Dockerfile;无 daemon 让并发构建互不干扰(每 job 独立存储),配合--storage-driver=vfs或独立 buildroot 避免锁冲突;gitlab-ci/github runner 上直接替换 docker 命令零成本; - 镜像签名与供应链:containers 生态的 Skopeo 可
skopeo copy在 registry 间搬镜像(不落本地 docker daemon);配合 sigstore/cosign 签名与 policy.json 策略(/etc/containers/policy.json限定只允许可信 registry)——与第 17 篇 Trivy 组成"扫描+准入"闭环; - K8s 节点运行时:
--cgroup-manager=systemd等参数注意与 kubelet 保持一致;CRI-O(同族兄弟)是 K8s 侧的对应物——Podman 面向开发者单机,CRI-O 面向节点运行时; - 网络差异注意:rootless 下端口 <1024 需要配置(
net.ipv4.ip_unprivileged_port_start);默认用 slirp4netns/pasta 做用户态网络,性能略低于 root 模式的 veth——大吞吐场景实测后再定; - 兼容性清单:Docker Compose 用
podman-compose或 podman 原生podman compose(兼容大部分场景);Docker Socket 兼容层podman system service可临时安抚那些硬编码 docker.sock 的工具; - macOS/Windows:容器是 Linux 内核特性,Podman 在非 Linux 上靠 VM(podman machine)——开发体验 Docker Desktop 与 Podman Desktop 目前差距不大,按团队生态选。
5、横向对比
| 维度 | Docker | Podman | containerd(nerdctl) |
|---|---|---|---|
| daemon | 有(root) | 无 | 有(轻量,K8s 标配) |
| rootless | 支持但非默认 | 默认一等公民 | 支持 |
| systemd 集成 | restart 策略 | Quadlet 原生 | 无 |
| pod 概念 | ❌ | ✅(含导出 K8s YAML) | ❌ |
| 生态成熟度 | 最广 | 快速追赶(RHEL 系默认) | K8s 运行时主流 |
选型直觉:个人开发机安全敏感/无 root 权限 → Podman;企业 Linux 服务器自托管服务 → Podman + Quadlet;K8s 集群节点 → containerd/CRI-O;跨平台团队统一工具链 → 仍以 Docker 为主(但值得试点迁移)。
6、深挖:rootless 的原理与边界
user namespace 映射:
宿主:/etc/subuid: dev:100000:65536
容器内 uid 0(root)──映射──> 宿主 uid 100000(dev 的子区间)
容器内 uid 1-65535 ──映射──> 宿主 uid 100001-165535
→ 容器内"至高权限"在宿主上只是普通账号区间
边界(rootless 的代价):
- 不能绑定 <1024 端口(可调内核参数)、不能用 ping(需 sysctl)、cgroup 受限(无 CPU/内存硬限制的完整语义,cgroup v2 已大幅改善);
- 挂载文件系统、修改宿主网络栈等"真 root"操作不可用——这不是缺陷,是安全边界本身。
7、面试高频问答
- Q:没有 daemon,容器怎么开机自启? A:容器进程由 systemd 服务(Quadlet 生成)直接管理,
systemctl start即podman run——把"进程管理"还给操作系统的进程管理器,而不是在 daemon 里再实现一套重试/依赖逻辑。 - Q:
alias docker=podman有坑吗? A:95% 命令兼容;差异点:docker context、部分 compose 高级特性、socket 编程的工具(需要podman system service兼容层)。迁移先跑podman info与现有 compose 文件验证。 - Q:rootless 容器安全在哪一层? A:user namespace 的 UID 映射让"容器内 root ≠ 宿主 root";即使容器逃逸(runc 漏洞),攻击者拿到的是宿主普通用户权限,配合文件系统权限还能再收敛一层。安全是纵深,不是银弹。
- Q:为什么 Red Hat 全系转向 Podman/CRI-O? A:企业场景要的是"无特权运维面 + systemd 生态融合 + CVE 面收敛"——daemonless 架构同时满足三点,且与 K8s 节点运行时(CRI-O)共享工具链。
8、总结
Podman 证明了容器世界的"更好的架构"可以后发制人:去掉 daemon、拥抱 rootless、融入 systemd、原生 pod/K8s 亲和。它未必立刻取代 Docker 的桌面心智,但在服务器与安全敏感环境已是更优解。理解它的设计动机(对照 Docker daemon 的三宗罪),比记住命令差异更重要——架构课永远大于工具课。
9、参考资料
- 官方文档:https://docs.podman.io/
- GitHub:https://github.com/containers/podman
- rootless 指南:https://github.com/containers/podman/blob/main/docs/tutorials/rootless-tutorial.md
- 本系列第 17 篇(镜像供应链安全)、第 21 篇(K3s 轻量运行时生态)


