4. Podman 容器引擎#

        flowchart LR
    subgraph Docker
        DC[docker CLI] --> DD[dockerd<br/>daemon]
        DD --> C1[Container]
    end
    subgraph Podman
        PC[podman CLI] --> R[conmon + runc<br/>no daemon]
        R --> C2[Container]
        PC --> Pod[Pod<br/>shared namespace]
        Pod --> C3[Container A]
        Pod --> C4[Container B]
    end
    style DD fill:#f99
    style R fill:#9f9
    

Podman 与 Docker 对比#

特性

Docker

Podman

架构

客户端-服务器(需要守护进程)

无守护进程(fork-exec 模型)

是否需要 root 权限

默认需要

默认无需 root(Rootless)

Pod 支持

不支持(仅通过 Compose 编排)

原生支持 Pod

Systemd 集成

有限

原生支持(Quadlet)

生成 K8s YAML

不支持

podman generate kube

CLI 兼容性

可作为 Docker 的直接替代

Compose 支持

原生支持

通过 podman-compose 或 docker-compose

安装#

# Ubuntu
sudo apt-get install podman

# macOS
brew install podman
podman machine init
podman machine start

# Alias for Docker compatibility
alias docker=podman

基本命令(兼容 Docker)#

# Run a container
podman run -d --name web -p 8080:80 nginx:1.25-alpine

# List containers
podman ps -a

# Logs
podman logs -f web

# Exec
podman exec -it web /bin/sh

# Stop and remove
podman stop web && podman rm web

# Build image
podman build -t myapp:1.0 .

# Push to registry
podman push myapp:1.0 docker.io/myuser/myapp:1.0

Podman 的命令行接口与 Docker 几乎完全一致,大多数情况下只需将 docker 替换为 podman 即可。

无根容器(Rootless Containers)#

# Podman runs rootless by default
podman run -d --name web -p 8080:80 nginx:1.25-alpine

# Check user namespace mapping
podman unshare cat /proc/self/uid_map

# Rootless networking uses slirp4netns or pasta
podman run --network pasta -p 8080:80 nginx:1.25-alpine

Podman 默认以非 root 用户运行容器,通过用户命名空间(User Namespace)实现权限隔离。无根模式下的网络由 slirp4netns 或 pasta 提供支持。

Pod(类似 Kubernetes 的分组机制)#

# Create a pod with shared network namespace
podman pod create --name myapp -p 8080:80 -p 3306:3306

# Add containers to the pod
podman run -d --pod myapp --name web nginx:1.25-alpine
podman run -d --pod myapp --name db \
  -e MYSQL_ROOT_PASSWORD=secret mysql:8.0

# Containers in the same pod share localhost
# web can reach db at localhost:3306

# List pods
podman pod ls

# Stop/remove pod (and all containers)
podman pod stop myapp
podman pod rm myapp

同一个 Pod 内的容器共享网络命名空间,彼此之间可以通过 localhost 直接通信,这与 Kubernetes 中 Pod 的行为一致。

生成 Kubernetes YAML#

# Generate K8s YAML from a running pod
podman generate kube myapp > myapp-k8s.yaml

# Play K8s YAML with podman
podman play kube myapp-k8s.yaml

# Tear down
podman play kube --down myapp-k8s.yaml

这一功能使得开发者可以在本地用 Podman 调试,然后将配置直接导出为 Kubernetes YAML 部署到集群中,实现从开发到生产的平滑过渡。

Systemd 集成(Quadlet)#

~/.config/containers/systemd/(无根模式)或 /etc/containers/systemd/(root 模式)下创建 .container 文件:

# ~/.config/containers/systemd/web.container
[Container]
Image=nginx:1.25-alpine
PublishPort=8080:80
Volume=web_data:/usr/share/nginx/html:ro

[Service]
Restart=always

[Install]
WantedBy=default.target
# Reload and start
systemctl --user daemon-reload
systemctl --user start web
systemctl --user enable web
systemctl --user status web

Quadlet 是 Podman 提供的 Systemd 原生集成方案,可以像管理系统服务一样管理容器,支持开机自启、自动重启等特性。

Podman Compose#

# Install podman-compose
pip install podman-compose

# Use existing docker-compose.yml
podman-compose up -d
podman-compose down

# Or use docker-compose with podman socket
systemctl --user start podman.socket
export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/podman/podman.sock
docker-compose up -d

从 Docker 迁移到 Podman#

  1. 安装 Podman 并设置别名 alias docker=podman

  2. 替换 Docker Socket:启用 podman.socket,为依赖 Docker Socket 的工具提供兼容接口

  3. 更新 CI/CD 流水线:将 docker 命令替换为 podman

  4. Systemd 服务迁移:将 Docker 的 Systemd 单元文件转换为 Quadlet 文件

  5. Compose 文件:使用 podman-compose 或通过 Podman Socket 运行 docker-compose

  6. 测试无根模式:确保所有工作负载在非 root 环境下正常运行

# Verify compatibility
podman info
podman system connection list