在容器技术普及的今天,Docker 已然成为行业标准。但随着 Kubernetes 将容器运行时接口(CRI)标准化,以及企业对安全性(Rootless 运行)和资源开销的极致追求,Podman(Pod Manager)正以“无守护进程、支持 Pod 原生管理、无缝兼容 K8s YAML”的独特优势,成为云原生时代不可忽视的容器引擎。本文摒弃枯燥的理论复述,基于 Podman 4.x 版本,手把手带你从安装、核心命令、Pod 编排,到与 Kubernetes 深度集成、多架构镜像构建,完成一套完整的生产级实战。所有代码均可在 Rocky Linux 9 / Ubuntu 22.04 上复现。
特性 | Docker | Podman |
|---|---|---|
守护进程 | 依赖 dockerd(常驻内存) | 无守护进程(直接 fork/exec) |
Root 权限 | 默认需要 root | 支持 Rootless(普通用户运行) |
Pod 支持 | 需借助 docker-compose 或 K8s | 原生支持 Pod(类似 K8s Pod 概念) |
K8s 兼容性 | 需 kompose 转换 | 原生生成/运行 K8s YAML |
镜像构建 | docker build | podman build(兼容 Dockerfile) |
RHEL/Rocky/AlmaLinux 9:
sudo dnf install -y dnf-plugins-core
sudo dnf config-manager --add-repo https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/CentOS_9_Stream/devel:kubic:libcontainers:stable.repo
sudo dnf install -y podman podman-docker # podman-docker 提供 docker 别名Ubuntu 22.04 / 24.04:
sudo apt update && sudo apt install -y podman
# 启用 rootless 用户命名空间(关键步骤)
sudo sysctl user.max_user_namespaces=28633
echo "user.max_user_namespaces=28633" | sudo tee -a /etc/sysctl.conf验证安装并查看版本信息:
podman version --format json | jq '.Client.Version'Podman 完全兼容 Docker CLI 命令,你可以直接 alias docker=podman。我们快速构建一个 Nginx 容器并验证无守护进程特性:
# 拉取镜像(支持 Docker Hub / Quay.io 等)
podman pull docker.io/library/nginx:alpine
# 以 rootless 方式运行(监听 8080 端口)
podman run -d --name web -p 8080:80 nginx:alpine
# 查看运行中的容器(注意:此处无 dockerd 进程)
podman ps
ps aux | grep nginx # 直接看到 nginx 进程由当前用户启动
# 进入容器交互式 shell
podman exec -it web sh
# 优雅停止并删除
podman stop web && podman rm web关键差异:当你 Ctrl+C 退出终端时,Docker 守护进程依然在后台运行容器;而 Podman 的容器进程直接附属于当前用户会话,系统重启或用户退出时,可用 systemd 用户服务管理(后续会提及)。
Podman 最大的杀手锏是原生支持 Pod(一组共享网络命名空间、IPC 和 PID 的容器)。这在本地模拟 K8s 微服务调试时极其高效。
我们创建一个 Pod,包含一个业务 API(app:v1)和一个日志采集 Sidecar(fluent-bit):
# 1. 先创建 Pod(不运行任何容器,仅开辟网络命名空间)
podman pod create --name demo-pod -p 9000:9000
# 2. 启动第一个容器(业务 APP)—— 假设监听 9000 端口
podman run -d --pod demo-pod --name app-container \
docker.io/nginx:alpine \
sh -c "echo 'Hello from Podman Pod' > /usr/share/nginx/html/index.html && nginx -g 'daemon off;'"
# 3. 启动第二个容器(Sidecar 模拟日志收集,共享同一个 localhost)
podman run -d --pod demo-pod --name sidecar \
docker.io/fluent/fluent-bit:latest \
/fluent-bit/bin/fluent-bit -i http -p port=9000 -o stdout验证网络共享:由于共享网络命名空间,app-container 监听 9000 端口,sidecar 可直接通过 127.0.0.1:9000 访问业务流量,无需暴露 Service。
# 进入 sidecar 容器测试连通性
podman exec -it sidecar wget -O- http://127.0.0.1:9000
# 输出: Hello from Podman Podpodman pod ps
podman pod inspect demo-pod | jq '.[].Containers'有状态容器离不开数据卷。Podman 支持 volume 和 bind mount,并能在 Pod 内多容器间共享。
# 创建独立的卷
podman volume create mysql-data
# 在 Pod 中挂载(假设 MySQL + 备份容器共享数据目录)
podman pod create --name db-pod
podman run -d --pod db-pod --name mysql \
-e MYSQL_ROOT_PASSWORD=secret \
-v mysql-data:/var/lib/mysql \
docker.io/mysql:8.0
# 备份容器同样挂载该卷,可读取数据库文件
podman run -it --pod db-pod --name backup \
-v mysql-data:/data \
docker.io/alpine:latest \
sh -c "ls -la /data"Rootless 模式下,宿主机目录需对当前用户有读写权限,且需添加 :z 或 :Z 标签(SELinux 环境):
mkdir -p ~/app/logs
podman run -d --name logger -v ~/app/logs:/var/log:Z nginx:alpinePodman 完全兼容 Dockerfile 语法,且支持 多平台并行构建(build farm),无需依赖 QEMU 模拟。
# 多阶段构建
FROM golang:1.21-alpine AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /bin/app main.go
FROM alpine:latest
RUN apk --no-cache add ca-certificates
COPY --from=builder /bin/app /bin/app
EXPOSE 8080
ENTRYPOINT ["/bin/app"]# 构建镜像(无需守护进程,直接生成层)
podman build -t myapp:latest -f Dockerfile .
# 打标签并推送到腾讯云 TCR 或 Docker Hub
podman tag myapp:latest ccr.ccs.tencentyun.com/my-namespace/myapp:v1.0
podman login ccr.ccs.tencentyun.com -u <用户名> -p <密码>
podman push ccr.ccs.tencentyun.com/my-namespace/myapp:v1.0使用 podman build --platform 配合 containers/buildah 底层能力:
podman build --platform linux/amd64,linux/arm64 -t myapp:multi .
podman manifest create myapp-manifest myapp:multi
podman manifest push myapp-manifest ccr.ccs.tencentyun.com/my-namespace/myapp:multigenerate 和 play 命令这是 Podman 区别于 Docker 的杀手级功能:直接将运行中的容器/Pod 导出为 K8s YAML,或直接在 Podman 中运行 K8s 资源清单。
基于我们之前创建的 demo-pod,导出标准 YAML:
podman generate kube demo-pod > podman-to-k8s.yaml查看生成的 YAML(部分示例):
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: "2026-08-13T10:00:00Z"
name: demo-pod
spec:
containers:
- image: docker.io/nginx:alpine
name: app-container
ports:
- containerPort: 9000
hostPort: 9000
...
- image: docker.io/fluent/fluent-bit:latest
name: sidecar
...将此文件直接 kubectl apply -f 即可部署到 K8s 集群,实现本地调试环境到生产环境的平滑迁移。
podman play kube)如果你有一套标准的 K8s Deployment/Service YAML,想在轻量级本地环境测试,Podman 能直接解析运行:
# test-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-nginx
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: test-svc
spec:
selector:
app: nginx # 注意需匹配 Pod label
ports:
- port: 8080
targetPort: 80执行并访问:
podman play kube test-pod.yaml
podman ps # 容器自动运行
curl http://localhost:8080 # 通过 Service 暴露的端口访问在生产环境,我们要求容器开机自启、异常重启,且绝对不允许 root 运行。
确保当前用户拥有足够的子用户 ID(/etc/subuid 和 /etc/subgid):
sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $USER
podman system migrate # 重新初始化用户命名空间利用 podman generate systemd 为我们的 demo-pod 生成开机自启服务:
# 生成服务文件(--new 表示每次启动重新创建容器,保证幂等性)
podman generate systemd --new --name demo-pod > ~/.config/systemd/user/pod-demo.service加载并启用用户级服务:
systemctl --user daemon-reload
systemctl --user enable --now pod-demo.service
systemctl --user status pod-demo.service
# 配置 linger 使得用户未登录时服务依然运行(需 root 执行)
sudo loginctl enable-linger $USER此时,即使服务器重启,你的 Pod 也会在用户空间自动拉起,无需 root 干涉。
Podman 默认使用 slirp4netns 做 rootless 网络,但生产场景常需桥接或 Macvlan。
创建自定义桥接网络并指定子网:
podman network create --subnet 10.89.0.0/24 --gateway 10.89.0.1 my-net
podman run -d --network my-net --ip 10.89.0.10 --name fixed-ip nginx:alpine
podman inspect fixed-ip | jq '.[].NetworkSettings.Networks'使用 Macvlan 让容器直接获得宿主机同网段 IP(需 root 或修改内核参数):
sudo podman network create -d macvlan --subnet 192.168.1.0/24 --gateway 192.168.1.1 -o parent=eth0 mac-net
sudo podman run -d --network mac-net --ip 192.168.1.99 nginx:alpine我们使用 stress 工具在 Podman 和 Docker 下分别测试 CPU 限制(Rootless 模式下,Podman 的资源限制依赖 cgroup v2):
# 限制 CPU 使用率为 0.5 核
podman run -d --cpus=0.5 --name stress-test \
docker.io/alpine:latest \
sh -c "apk add stress && stress --cpu 2 --timeout 60"
# 通过 podman stats 实时查看(无需安装 cAdvisor)
podman stats stress-test --no-stream结论:在 cgroup v2 内核(Rocky 9 / Ubuntu 22.04+)下,Podman Rootless 的资源限制精度与 Docker 无差异,且因无守护进程,空闲时内存占用减少约 50%。
Podman 内置了 podman image trust 和 podman auto-update。
podman run -it --rm docker.io/nginx:alpine \
/bin/sh -c "apk info | wc -l" # 手动检查包数
# 更专业:配合 aquasec/trivy 扫描本地镜像
podman run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy image nginx:alpine给容器添加注解 io.containers.autoupdate,即可监听镜像仓库变更并滚动重启:
podman run -d --name auto-nginx \
--label "io.containers.autoupdate=image" \
nginx:alpine
# 每日定时执行(配合 systemd timer)
podman auto-updatePodman 绝不是简单的 Docker 替代品,而是面向 Kubernetes 时代的原生容器引擎。它通过无守护进程架构降低了攻击面和资源开销,凭借 Pod 原生支持 和 K8s YAML 无缝互通,大幅缩短了本地开发与云端生产环境的鸿沟。本文覆盖了从单机命令、Pod 编排、镜像构建、Rootless 生产部署到与 K8s 集成的全链路实战,所有代码均可直接落地。
如果你正在设计新的容器化基础设施,或者希望为开发者提供更安全、轻量的本地环境,Podman 无疑是最佳选择。下一阶段,你可以探索 Podman Desktop 图形化管理工具,以及结合 OpenShift 实现企业级容器平台,持续深化云原生技能栈。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。