podman与docker的区别和生产环境最佳实践

前言

docker 是一个很好用的容器工具,但目前已经式微,而podman因为出厂设置就是rootless,深受安全专家喜爱,下面呢就简单介绍docker和podman的区别,并给出podman的安全实践。


架构设计:最核心的区别

两者最根本的区别在于是否依赖守护进程(Daemon)

  • Docker 采用 Client-Server 架构 ,核心是一个始终运行的后台守护进程 dockerd,所有容器操作都通过它中转。客户端 CLI 向 daemon 发送指令,daemon 再调用底层 containerd 执行。

  • PodmanDaemonless(无守护进程)架构,每次执行命令时直接 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-composedocker-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 将这些能力都做成了原生一等公民,无需复杂的外部工具链。

相关推荐
程途知微2 小时前
ConcurrentHashMap线程安全实现原理全解析
java·后端
Mars酱2 小时前
1分钟编写贪吃蛇 | JSnake贪吃蛇单机版
java·后端·开源
卷卷说风控2 小时前
养了10年风控,今年开始养「虾」了
后端
王码码20352 小时前
Go语言中的Elasticsearch操作:olivere实战
后端·golang·go·接口
小旭95273 小时前
Spring Security 实现权限控制(认证 + 授权全流程)
java·后端·spring
weixin_408099673 小时前
【完整教程】天诺脚本如何调用 OCR 文字识别 API?自动识别屏幕文字实战(附代码)
前端·人工智能·后端·ocr·api·天诺脚本·自动识别文字脚本
金銀銅鐵3 小时前
[Java] 如何通过 cglib 的 FastClass 调用一个类中的“任意”方法?
java·后端
宠友信息3 小时前
一套基于uniapp+springboot完整社区系统是如何实现的?友猫社区源码级功能解析
java·spring boot·后端·微服务·微信·uni-app
小信丶4 小时前
Spring Cloud Stream EnableBinding注解详解:定义、应用场景与示例代码
java·spring boot·后端·spring