前言
docker 是一个很好用的容器工具,但目前已经式微,而podman因为出厂设置就是rootless,深受安全专家喜爱,下面呢就简单介绍docker和podman的区别,并给出podman的安全实践。
架构设计:最核心的区别
两者最根本的区别在于是否依赖守护进程(Daemon)。
-
Docker 采用 Client-Server 架构 ,核心是一个始终运行的后台守护进程
dockerd,所有容器操作都通过它中转。客户端 CLI 向 daemon 发送指令,daemon 再调用底层containerd执行。 -
Podman 是 Daemonless(无守护进程)架构,每次执行命令时直接 fork/exec 子进程来管理容器,不依赖任何常驻后台服务。
makefile
Docker: CLI → dockerd (root daemon) → containerd → runc → container
Podman: CLI → fork/exec → conmon → runc → container
这一架构差异,是后续几乎所有特性差异的根源。
安全性对比
安全性是 Podman 最大的竞争优势之一。
Rootless 容器(无 Root 运行)
- Podman 原生支持以普通用户身份运行容器,无需任何 sudo 权限,容器进程在宿主机上以当前用户 UID 运行。
- Docker 的 daemon 默认以 root 权限运行,即使客户端是普通用户,实际操作仍经过特权进程。虽然后来也支持 rootless 模式,但配置复杂,并非默认行为。
攻击面
- Docker daemon 长期以 root 运行,一旦被攻击或出现漏洞,整个宿主机都面临风险(经典的"docker 组等同于 root"问题)。
- Podman 无 daemon,攻击面大幅缩小,符合最小权限原则。
SELinux / Seccomp 集成
- Podman 由 Red Hat 主导开发,与 SELinux 集成更深,在 RHEL/Fedora/CentOS 系上开箱即用。
功能特性对比
| 特性 | Docker | Podman |
|---|---|---|
| 守护进程 | ✅ 需要 dockerd |
❌ 无守护进程 |
| Rootless 运行 | ⚠️ 支持但非默认 | ✅ 原生默认支持 |
| CLI 兼容性 | Docker CLI | 完全兼容 Docker CLI(alias 即可替换) |
| Pod 概念支持 | ❌ 不支持(需 K8s) | ✅ 原生支持 Pod(多容器组) |
| Systemd 集成 | ⚠️ 需额外配置 | ✅ podman generate systemd 原生生成 |
| Docker Compose | ✅ 官方支持 | ✅ 通过 podman-compose 或 docker-compose 兼容 |
| 镜像构建 | docker build / BuildKit |
podman build(基于 Buildah) |
| 镜像仓库兼容 | Docker Hub 优先 | 支持多仓库(Docker Hub / Quay / GHCR 等) |
| Windows/macOS 支持 | ✅ Docker Desktop 成熟 | ⚠️ Podman Desktop 较新,体验稍弱 |
| Swarm 集群 | ✅ 内置 Docker Swarm | ❌ 不支持(推荐直接用 K8s) |
| 开源协议 | Apache 2.0(部分商业化) | 完全开源,Apache 2.0 |
| 商业支持 | Docker Inc. 商业产品 | Red Hat / 社区驱动 |
Podman 独有亮点
1. 原生 Pod 支持
Podman 直接借鉴了 Kubernetes 的 Pod 概念,可以将多个容器组合为一个 Pod,共享网络命名空间:
bash
podman pod create --name mypod
podman run --pod mypod nginx
podman run --pod mypod redis
这让本地开发与 K8s 部署的心智模型高度一致。
2. 生成 Kubernetes YAML
bash
podman generate kube mypod > mypod.yaml
可直接将本地 Pod 导出为 K8s 兼容的 YAML,本地开发 → K8s 部署无缝衔接。
3. Systemd 服务生成
bash
podman generate systemd --new mycontainer > /etc/systemd/system/mycontainer.service
容器即服务,天然融入 Linux 服务管理体系。
🐳 Docker 的优势
Docker 并非没有优势,在以下场景仍更具竞争力:
- 生态成熟度:Docker Hub、Docker Compose、Docker Desktop 生态极为完善。
- Windows/macOS 体验:Docker Desktop 在非 Linux 平台上体验更流畅。
- 企业工具链兼容:大量 CI/CD 工具(Jenkins、GitHub Actions 等)默认集成 Docker。
- 学习资源:文档、教程、社区问答资源远多于 Podman。
- BuildKit:Docker 的 BuildKit 构建引擎功能强大,缓存机制更成熟。
选型建议
| 场景 | 推荐 |
|---|---|
| 企业生产环境 + RHEL/Fedora | ✅ Podman |
| 安全敏感环境(无 root 要求) | ✅ Podman |
| 本地开发 + K8s 部署对齐 | ✅ Podman |
| Windows/macOS 桌面开发 | ✅ Docker Desktop |
| 已有大量 Compose 工作流 | ✅ Docker(或 podman-compose 迁移) |
| 初学者入门容器技术 | ✅ Docker(生态更友好) |
| CI/CD 流水线(通用) | 两者均可,视平台而定 |
一句话: Podman 是"更安全、更 Linux 原生、更贴近 K8s"的现代化选择;Docker 是"生态最成熟、上手最快、跨平台最友好"的工业标准。两者 CLI 高度兼容,迁移成本极低,甚至可以 alias docker=podman 无缝切换。
最佳实践
Podman 的使用方式与 Docker 高度相似,但在安全配置上有更多原生能力可以利用。下面从安装到生产级安全加固,给出完整的实战指南
📦 一、安装与初始化
RHEL / CentOS / Fedora
bash
# Fedora(默认已预装)
sudo dnf install -y podman
# RHEL 8/9 / CentOS Stream
sudo dnf install -y podman
Ubuntu / Debian
bash
sudo apt-get update
sudo apt-get install -y podman
macOS(via Homebrew)
bash
brew install podman
podman machine init # 初始化虚拟机
podman machine start # 启动 Podman Machine
验证安装
bash
podman --version
podman info # 查看运行时详细信息
🔐 二、Rootless 模式配置(核心安全基础)
Rootless 是 Podman 最重要的安全特性,强烈建议始终以普通用户身份运行。
前置条件检查
bash
# 检查用户命名空间支持
cat /proc/sys/kernel/unprivileged_userns_clone
# 输出应为 1,若为 0 则需开启:
echo 'kernel.unprivileged_userns_clone=1' | sudo tee /etc/sysctl.d/99-userns.conf
sudo sysctl --system
# 检查 /etc/subuid 和 /etc/subgid(必须存在当前用户条目)
grep $(whoami) /etc/subuid /etc/subgid
# 若无,手动添加:
sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $(whoami)
初始化 Rootless 环境
bash
# 以普通用户身份迁移命名空间
podman system migrate
# 验证 rootless 状态
podman info | grep rootless
# 应输出:rootless: true
🚀 三、基础容器操作
拉取与运行镜像
bash
# 拉取镜像(默认从 docker.io,可指定仓库)
podman pull docker.io/library/nginx:alpine
podman pull quay.io/fedora/fedora:latest
# 运行容器(基本)
podman run -d --name mynginx -p 8080:80 nginx:alpine
# 运行并自动删除(临时容器)
podman run --rm -it alpine sh
# 指定用户运行(安全加固)
podman run --user 1001:1001 nginx:alpine
容器生命周期管理
bash
podman ps # 查看运行中的容器
podman ps -a # 查看所有容器(含已停止)
podman stop mynginx # 优雅停止
podman start mynginx # 启动
podman restart mynginx # 重启
podman rm mynginx # 删除容器
podman rm -f mynginx # 强制删除
镜像管理
bash
podman images # 列出本地镜像
podman rmi nginx:alpine # 删除镜像
podman image prune # 清理悬空镜像
podman system prune -a # 清理所有未使用资源
🏗️ 四、构建镜像(基于 Buildah)
Podman 内置 Buildah 引擎,podman build 完全兼容 Dockerfile 语法。
编写安全的 Dockerfile
dockerfile
# ✅ 安全最佳实践示例
FROM node:20-alpine AS builder
# 使用非 root 用户
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN chown -R appuser:appgroup /app
# 多阶段构建,最小化最终镜像
FROM node:20-alpine
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
COPY --from=builder --chown=appuser:appgroup /app .
USER appuser # ✅ 非 root 运行
EXPOSE 3000
CMD ["node", "server.js"]
构建命令
bash
# 基本构建
podman build -t myapp:1.0 .
# 多平台构建
podman build --platform linux/amd64,linux/arm64 -t myapp:1.0 .
# 不使用缓存(安全扫描前推荐)
podman build --no-cache -t myapp:1.0 .
# 查看镜像层(审计用)
podman history myapp:1.0
🛡️ 五、安全加固措施(重点)
这是 Podman 区别于 Docker 的核心价值所在,以下措施应作为生产环境标准配置。
5.1 能力(Capabilities)限制
bash
# 删除所有能力,只保留必要的
podman run \
--cap-drop=ALL \
--cap-add=NET_BIND_SERVICE \ # 仅添加绑定低端口的能力
-d nginx:alpine
# 查看容器当前能力
podman inspect mynginx | grep -A 10 CapAdd
5.2 只读根文件系统
bash
podman run \
--read-only \ # 根文件系统只读
--tmpfs /tmp:rw,size=64m,mode=1777 \ # 临时目录可写
--tmpfs /var/run:rw \
-d nginx:alpine
5.3 资源限制(防止资源耗尽攻击)
bash
podman run \
--memory=512m \ # 内存上限
--memory-swap=512m \ # 禁止使用 swap
--cpus=1.0 \ # CPU 核心数限制
--pids-limit=100 \ # 进程数限制(防 fork bomb)
--ulimit nofile=1024:1024 \
-d myapp:1.0
5.4 Seccomp 安全配置文件
bash
# 使用默认 seccomp 配置(已自动启用)
podman run --security-opt seccomp=/usr/share/containers/seccomp.json nginx
# 使用自定义严格配置
podman run --security-opt seccomp=/path/to/custom-seccomp.json myapp
# 查看当前 seccomp 状态
podman inspect mynginx | grep -i seccomp
5.5 SELinux 标签(RHEL/Fedora 专属)
bash
# 自动应用 SELinux 标签
podman run --security-opt label=type:container_t nginx
# 挂载卷时添加 SELinux 标签(:z 共享,:Z 私有)
podman run -v /host/data:/app/data:Z,ro nginx
# ↑ ↑
# SELinux标签 只读挂载
5.6 网络隔离
bash
# 创建隔离网络
podman network create --internal mynet # internal=无外网访问
# 容器加入指定网络
podman run --network mynet -d myapp
# 完全禁用网络(适合纯计算任务)
podman run --network none myapp
# 查看网络
podman network ls
podman network inspect mynet
5.7 完整安全加固示例(生产推荐模板)
bash
podman run -d \
--name secure-app \
--user 1001:1001 \ # 非 root 用户
--cap-drop=ALL \ # 删除所有能力
--cap-add=NET_BIND_SERVICE \ # 按需添加
--read-only \ # 只读文件系统
--tmpfs /tmp:rw,size=32m \ # 临时目录
--memory=256m \ # 内存限制
--memory-swap=256m \ # 禁用 swap
--cpus=0.5 \ # CPU 限制
--pids-limit=50 \ # 进程数限制
--security-opt no-new-privileges \ # 禁止提权
--security-opt seccomp=default \ # seccomp 过滤
--network mynet \ # 隔离网络
-v /host/config:/app/config:ro,Z \ # 只读挂载 + SELinux
-p 127.0.0.1:8080:8080 \ # 仅绑定本地回环
myapp:1.0
🔑
--security-opt no-new-privileges是最重要的单条安全指令,可防止容器内进程通过 setuid/setgid 提升权限。
🫛 六、Pod 管理(Podman 特色功能)
bash
# 创建 Pod(共享网络命名空间)
podman pod create \
--name webapp \
-p 8080:80 \
--network mynet
# 向 Pod 添加容器
podman run -d --pod webapp --name nginx nginx:alpine
podman run -d --pod webapp --name redis redis:alpine
# 查看 Pod 状态
podman pod ps
podman pod inspect webapp
# Pod 整体操作
podman pod stop webapp
podman pod start webapp
podman pod rm webapp --force
# 导出为 Kubernetes YAML(本地 → K8s 无缝迁移)
podman generate kube webapp > webapp-k8s.yaml
⚙️ 七、Systemd 集成(生产服务化)
将容器作为系统服务管理,实现开机自启、崩溃自恢复。
bash
# 生成 systemd service 文件
podman generate systemd \
--new \ # 每次启动重新创建容器
--name \ # 使用容器名
--restart-policy=always \
mynginx > ~/.config/systemd/user/container-mynginx.service
# 启用并启动服务(rootless 用户级)
systemctl --user daemon-reload
systemctl --user enable --now container-mynginx.service
# 查看服务状态
systemctl --user status container-mynginx.service
journalctl --user -u container-mynginx.service -f
# 开机自启(需要 linger 支持)
sudo loginctl enable-linger $(whoami)
🔍 八、日志与调试
bash
# 查看容器日志
podman logs mynginx
podman logs -f mynginx # 实时跟踪
podman logs --tail=100 mynginx # 最后 100 行
# 进入容器调试
podman exec -it mynginx sh
# 查看容器资源使用
podman stats # 实时监控所有容器
podman stats mynginx --no-stream # 单次快照
# 查看容器详情
podman inspect mynginx
# 查看容器进程
podman top mynginx
# 检查容器文件系统变更
podman diff mynginx
📋 九、安全检查清单
在部署前,用这份清单做最终审查:
| 检查项 | 命令 | 期望结果 |
|---|---|---|
| 以非 root 运行 | `podman inspect <c> | grep User` |
| 无新权限 | `podman inspect <c> | grep NoNewPrivileges` |
| 只读文件系统 | `podman inspect <c> | grep ReadonlyRootfs` |
| 内存限制已设 | `podman inspect <c> | grep Memory` |
| 进程数限制 | `podman inspect <c> | grep PidsLimit` |
| 端口绑定检查 | podman port <c> |
仅绑定必要端口 |
| 镜像漏洞扫描 | podman image scan <image> 或 trivy image |
无高危漏洞 |
核心原则总结: Rootless 运行 + 最小权限能力 + 只读文件系统 + 资源限制 + 网络隔离,这五层防护叠加,可以构建出远超传统 Docker 部署的安全容器环境。Podman 将这些能力都做成了原生一等公民,无需复杂的外部工具链。