关于 podman
面向 Linux 容器运维人员的 Podman 技能,介绍无守护进程和无 root 运行容器,并涵盖 Pod、systemd 集成及镜像管理。
主要功能
- 01以无守护进程模式管理容器
- 02以 rootless 模式运行容器
- 03创建和管理 Pod
- 04生成 systemd 单元并使用 Quadlet
- 05管理镜像、网络和存储卷
- 06运行 Compose 文件和 Kubernetes YAML
适用场景
- 01在无需 root 权限时运行容器
- 02在没有 Docker 的系统上管理容器
- 03将相关容器编组成 Pod
- 04通过 systemd 管理容器服务
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ bagelhole/ devops-security-agent-skills --skill podman安装后在 Claude Code 中输入/podman确认已加载。
详细介绍
Podman
使用 Podman 的无根容器引擎,在无需守护进程的情况下运行和管理容器。
何时使用此技能
在以下情况下使用此技能:
- 无需 root 权限运行容器
- 在没有 Docker 的系统上管理容器
- 创建基于 Pod 的容器组
- 使用 systemd 管理容器
- 在注重安全的环境中工作
前置条件
- 已安装 Podman(4.x+)
- 无根模式:已启用用户命名空间
- 了解容器的基本概念
与 Docker 的主要区别
| 特性 | Docker | Podman |
|---|---|---|
| 架构 | 客户端—守护进程 | 无守护进程 |
| 是否需要 root | 默认需要 | 可选(无根模式) |
| Pod 支持 | 不支持 | 支持(Kubernetes 风格) |
| systemd 集成 | 有限 | 原生支持 |
| 套接字 | docker.sock | podman.sock(可选) |
基本命令
容器操作
# Run container (identical to Docker)
podman run -d --name webserver -p 8080:80 nginx
# List containers
podman ps -a
# Stop and remove
podman stop webserver
podman rm webserver
# Execute command
podman exec -it webserver /bin/sh
# View logs
podman logs -f webserver
镜像管理
# Pull image
podman pull docker.io/library/nginx:latest
# List images
podman images
# Build image
podman build -t myapp:latest .
# Push to registry
podman push myapp:latest registry.example.com/myapp:latest
# Remove image
podman rmi nginx:latest
无根容器
设置
# Check user namespace support
cat /proc/sys/user/max_user_namespaces
# Enable if needed (as root)
echo "user.max_user_namespaces=28633" | sudo tee /etc/sysctl.d/userns.conf
sudo sysctl -p /etc/sysctl.d/userns.conf
# Configure subuid/subgid for user
sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $USER
# Verify
podman unshare cat /proc/self/uid_map
以无根模式运行
# Run as regular user (no sudo)
podman run -d --name myapp -p 8080:80 nginx
# Check user namespace mapping
podman unshare id
# Verify non-root
podman top myapp user
端口注意事项
# Rootless cannot bind to ports < 1024 by default
# Use ports >= 1024
podman run -d -p 8080:80 nginx
# Or enable unprivileged ports (as root)
echo "net.ipv4.ip_unprivileged_port_start=80" | sudo tee /etc/sysctl.d/ports.conf
sudo sysctl -p /etc/sysctl.d/ports.conf
Pod
创建 Pod
# Create pod
podman pod create --name mypod -p 8080:80 -p 5432:5432
# Add containers to pod
podman run -d --pod mypod --name web nginx
podman run -d --pod mypod --name db postgres:15
# List pods
podman pod ps
# Containers share network namespace
podman exec web curl localhost:5432
Pod 管理
# Start/stop pod (affects all containers)
podman pod start mypod
podman pod stop mypod
# Remove pod and containers
podman pod rm -f mypod
# View pod details
podman pod inspect mypod
# Generate Kubernetes YAML from pod
podman generate kube mypod > mypod.yaml
systemd 集成
生成 systemd 单元
# Generate unit file for container
podman generate systemd --new --name myapp > ~/.config/systemd/user/container-myapp.service
# For pod
podman generate systemd --new --name mypod --files
# Reload systemd
systemctl --user daemon-reload
# Enable and start
systemctl --user enable --now container-myapp.service
Quadlet(Podman 4.4+)
# ~/.config/containers/systemd/webapp.container
[Container]
Image=docker.io/library/nginx:latest
PublishPort=8080:80
Volume=webapp-data:/usr/share/nginx/html
[Service]
Restart=always
[Install]
WantedBy=default.target
# Reload to generate service
systemctl --user daemon-reload
# Start the service
systemctl --user start webapp
Compose 兼容性
使用 Podman Compose
# Install podman-compose
pip install podman-compose
# Run compose file
podman-compose up -d
# Or use Docker Compose with Podman socket
systemctl --user enable --now podman.socket
export DOCKER_HOST=unix:///run/user/$UID/podman/podman.sock
docker-compose up -d
原生 Podman Kube
# Play Kubernetes YAML
podman kube play deployment.yaml
# Stop and remove
podman kube down deployment.yaml
网络
网络管理
# Create network
podman network create mynetwork
# Run on network
podman run -d --network mynetwork --name app myapp
# Connect container to network
podman network connect mynetwork existing-container
# List networks
podman network ls
# Inspect network
podman network inspect mynetwork
DNS 解析
# Containers on same network can resolve by name
podman run -d --network mynetwork --name db postgres:15
podman run -d --network mynetwork --name app \
-e DATABASE_HOST=db myapp
存储
卷管理
# Create volume
podman volume create mydata
# Use volume
podman run -d -v mydata:/data myapp
# List volumes
podman volume ls
# Inspect volume
podman volume inspect mydata
# Rootless volumes location
ls ~/.local/share/containers/storage/volumes/
绑定挂载
# Bind mount with SELinux label
podman run -v ./data:/app/data:Z myapp
# Z = private label (single container)
# z = shared label (multiple containers)
注册表配置
配置注册表
# Edit registries.conf
# ~/.config/containers/registries.conf
unqualified-search-registries = ["docker.io", "quay.io"]
[[registry]]
prefix = "docker.io"
location = "docker.io"
[[registry.mirror]]
location = "mirror.gcr.io"
身份验证
# Login to registry
podman login docker.io
# Login to private registry
podman login registry.example.com
# Credentials stored in
# ~/.config/containers/auth.json
构建镜像
Buildah 集成
# Podman uses Buildah for builds
podman build -t myapp:latest .
# Build with specific format
podman build --format docker -t myapp .
# Multi-stage build
podman build --target production -t myapp:prod .
Buildah 命令
# Create container from scratch
buildah from scratch
buildah copy working-container ./app /app
buildah config --entrypoint '["/app/main"]' working-container
buildah commit working-container myapp:minimal
常见问题
问题:权限被拒绝
问题:无法访问已挂载卷中的文件
解决方案:对 SELinux 使用 :Z 或 :z 后缀,或检查所有权
问题:无法连接到容器
问题:无根模式下端口无法访问
解决方案:使用大于等于 1024 的端口,或配置非特权端口起始值
问题:拉取镜像速度慢
问题:镜像下载速度慢
解决方案:在 registries.conf 中配置注册表镜像
问题:systemd 服务失败
问题:容器无法通过 systemd 启动
解决方案:启用 linger:loginctl enable-linger $USER
最佳实践
- 使用无根模式增强安全性
- 使用 Pod 管理相关容器
- 在生产环境中生成 systemd 单元
- 使用 Quadlet 声明式管理容器服务
- 为绑定挂载配置 SELinux 标签
- 为持久运行的服务启用用户 linger
- 使用 podman auto-update 自动更新
- 将
docker设置为podman的别名以实现兼容
相关技能
- docker-management - Docker 基础知识
- kubernetes-ops - K8s 编排
- container-hardening - 安全
评论
支持 Markdown