跳转至

Podman 容器引擎

一句话说明: Podman 是无守护进程(daemonless)的容器引擎,命令兼容 Docker,但以 rootless 模式运行更安全,且支持 Pod 概念原生对接 Kubernetes。


为什么要学

  1. 无守护进程 — 不需要后台 daemon 常驻,每个容器是独立进程,更安全稳定
  2. Rootless 容器 — 默认以普通用户运行容器,无需 root 权限,减小攻击面
  3. Docker CLI 兼容alias docker=podman 即可,迁移成本极低
  4. Pod 原生支持 — 直接生成 Kubernetes YAML,开发到部署无缝衔接
  5. RHEL/Fedora 默认 — Red Hat 生态的标准容器工具,企业级支持

核心概念详解

Podman vs Docker

特性PodmanDocker
架构无 daemon,fork-exec客户端-daemon
运行权限Rootless 默认需 root(或 docker 组)
安全性更高(无特权 daemon)daemon 有 root 权限
Pod 支持原生需 Docker Compose
Compose 兼容podman-compose / 兼容 docker-compose原生
Systemd 集成原生(quadlet)第三方
K8s YAML 生成podman generate kube
镜像格式OCI 标准OCI 标准
macOS/WindowsPodman Machine (VM)Docker Desktop (VM)

核心概念

概念说明
Container与 Docker 容器相同的 OCI 容器
Pod共享网络/IPC 命名空间的容器组(对应 K8s Pod)
ImageOCI 容器镜像,与 Docker 镜像通用
Volume持久化存储卷
Network容器网络(CNI/netavark)
Quadletsystemd 原生管理容器的方式

Rootless 工作原理

传统 Docker:
  用户 → docker CLI → docker daemon (root) → containerd → 容器

Podman rootless:
  用户 → podman CLI → conmon → 容器 (用户命名空间映射)

无特权 daemon,每个容器由 conmon(容器监控器)管理,崩溃不影响其他容器。

安装与配置

Linux

# Fedora/RHEL/CentOS
sudo dnf install podman

# Ubuntu/Debian
sudo apt install podman

# Arch Linux
sudo pacman -S podman

macOS

brew install podman

# 初始化虚拟机
podman machine init
podman machine start

Windows

# WSL2 中安装
wsl --install Ubuntu
# 然后在 WSL 中 apt install podman

# 或使用 Podman Desktop
winget install RedHat.Podman-Desktop

Rootless 配置(Linux)

# 通常安装后即可用,检查 subuid/subgid
cat /etc/subuid
cat /etc/subgid
# 应有类似: username:100000:65536

# 如果没有,手动添加
sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $USER

Docker 兼容别名

# 添加到 .bashrc/.zshrc
alias docker=podman

验证

podman --version
# podman version 5.3.0

podman info --format '{{.Host.Security.Rootless}}'
# true

快速上手

基本操作(与 Docker 完全相同)

# 拉取镜像
podman pull python:3.12-slim

# 运行容器
podman run -it --rm python:3.12-slim python -c "print('Hello Podman')"

# 后台运行
podman run -d --name myapp -p 8080:80 nginx

# 查看运行中的容器
podman ps

# 查看日志
podman logs myapp

# 进入容器
podman exec -it myapp bash

# 停止并删除
podman stop myapp
podman rm myapp

构建镜像

# 使用 Dockerfile(或 Containerfile)
podman build -t myapp:latest .

# 查看本地镜像
podman images

挂载卷

podman run -v ./data:/app/data:Z python:3.12 python /app/data/script.py
# :Z 标签处理 SELinux 上下文(Linux 特有)

进阶用法

1. Pod 管理

# 创建 Pod(共享网络)
podman pod create --name webapp -p 8080:80 -p 5432:5432

# 在 Pod 中添加容器
podman run -d --pod webapp --name db postgres:16
podman run -d --pod webapp --name app -e DB_HOST=localhost myapp

# Pod 内容器通过 localhost 互通
# db 和 app 共享网络命名空间

# 查看 Pod
podman pod ps
podman pod inspect webapp

# 停止/删除 Pod(包含所有容器)
podman pod stop webapp
podman pod rm webapp

2. 生成 Kubernetes YAML

# 从运行中的 Pod 生成 K8s 配置
podman generate kube webapp > webapp.yaml

# 用生成的 YAML 在 Podman 中重建
podman play kube webapp.yaml

# 也可以直接在 K8s 集群中使用
kubectl apply -f webapp.yaml

3. Podman Compose

# 安装 podman-compose
pip install podman-compose

# 使用已有 docker-compose.yml
podman-compose up -d
podman-compose down

# 或使用 Docker Compose(v2+ 兼容 Podman socket)
systemctl --user enable --now podman.socket
export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/podman/podman.sock
docker compose up -d

4. Quadlet(Systemd 集成)

创建 ~/.config/containers/systemd/myapp.container

[Unit]
Description=My Application
After=network-online.target

[Container]
Image=docker.io/library/nginx:latest
PublishPort=8080:80
Volume=./html:/usr/share/nginx/html:ro,Z

[Service]
Restart=always

[Install]
WantedBy=default.target
# 重新加载并启动
systemctl --user daemon-reload
systemctl --user start myapp
systemctl --user enable myapp

# 查看状态
systemctl --user status myapp

5. 多阶段构建

# Containerfile
FROM rust:1.75 AS builder
WORKDIR /app
COPY . .
RUN cargo build --release

FROM debian:bookworm-slim
COPY --from=builder /app/target/release/myapp /usr/local/bin/
EXPOSE 8080
CMD ["myapp"]
podman build -t myapp:latest -f Containerfile .

6. 镜像签名与验证

# 配置可信镜像源
# /etc/containers/policy.json

# 签名镜像
podman push --sign-by you@example.com myregistry.io/myapp:latest

# 拉取时验证签名
podman pull --tls-verify myregistry.io/myapp:latest

7. 网络管理

# 创建自定义网络
podman network create mynet

# 容器加入网络
podman run -d --network mynet --name api myapi
podman run -d --network mynet --name worker myworker

# 容器间通过名称通信
# worker 中可以 curl http://api:8080

# 查看网络
podman network ls
podman network inspect mynet

8. 资源限制

# CPU 和内存限制
podman run -d \
  --cpus=2 \
  --memory=1g \
  --memory-swap=2g \
  --name limited-app \
  myapp

# 查看资源使用
podman stats

9. 镜像加速(国内)

编辑 ~/.config/containers/registries.conf

unqualified-search-registries = ["docker.io"]

[[registry]]
prefix = "docker.io"
location = "docker.io"

[[registry.mirror]]
location = "mirror.ccs.tencentyun.com"

常见问题与排错

Q: "permission denied" 运行容器

# 检查 subuid/subgid 配置
podman unshare cat /proc/self/uid_map

# 重新映射
podman system migrate

Q: 端口 < 1024 无法绑定(rootless)

# 方法1: 使用高端口
podman run -p 8080:80 nginx

# 方法2: 允许非特权端口绑定
sudo sysctl net.ipv4.ip_unprivileged_port_start=80

Q: 存储空间不足

# 清理无用资源
podman system prune -a

# 查看存储使用
podman system df

Q: macOS 上容器无法访问主机服务

# macOS 使用虚拟机,主机地址为
# host.containers.internal 或 host.docker.internal
podman run --add-host=host.docker.internal:host-gateway myapp

Q: Docker Compose 文件不兼容

大部分 docker-compose.yml 可直接使用。已知差异: - network_mode: host 在 rootless 中行为不同 - 部分特权操作需要 --privileged - Volume SELinux 标签需要 :Z:z

Q: 如何与 VS Code Dev Container 集成

// .devcontainer/devcontainer.json
{
    "dockerComposeFile": "docker-compose.yml",
    "settings": {
        "dev.containers.dockerPath": "podman"
    }
}

或设置 VS Code:

"dev.containers.dockerPath": "podman"

参考资源

  • 官方文档:https://docs.podman.io
  • GitHub 仓库:https://github.com/containers/podman
  • Podman Desktop:https://podman-desktop.io
  • Quadlet 指南:https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html
  • 从 Docker 迁移:https://podman.io/docs/installation#migrating-from-docker
  • Red Hat 容器文档:https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/building_running_and_managing_containers
  • Awesome Podman:https://github.com/containers/podman/blob/main/awesome.md