podman安装使用
一、podman简介
Podman 是一个开源的容器引擎,由 Red Hat 主导开发,遵循 OCI(开放容器倡议)标准,用于管理容器、镜像和 Pod。 简单说,它就是一个可以替代 Docker 的容器管理工具,命令行几乎一模一样,但架构设计上有本质区别。
1.1 核心特点
- 无守护进程(Daemonless) Podman 不依赖常驻后台的守护进程(如 Docker 的 dockerd),而是直接通过 fork/exec 调用 OCI 运行时(runc/crun)启动容器。每个容器都是独立的子进程,由 systemd 或用户会话直接管理,消除了单点故障风险,空闲时几乎不占用系统资源。
-
原生 Rootless 模式 默认以普通用户权限运行容器,容器内的 root 用户通过 Linux 用户命名空间映射为宿主机上的非特权用户。即使容器逃逸,攻击面也被限制在当前用户范围内,符合最小权限原则。
-
原生 Pod 支持 内置 Kubernetes Pod 概念,可以将多个容器组合为一个逻辑单元,共享网络和 IPC 命名空间。支持通过
podman generate kube导出 K8s YAML,或通过podman play kube直接运行 K8s 配置,方便本地开发与生产环境衔接。 -
高度兼容 Docker 命令行与 Docker 90% 以上兼容,支持
alias docker=podman直接替换。兼容 Docker 镜像格式、Dockerfile 语法以及 Docker Hub 等镜像仓库。 -
深度集成 systemd 可通过
podman generate systemd生成 systemd 服务单元文件,将容器作为系统服务管理,实现开机自启、故障自动重启和日志接入 journald。
1.2 与Docker的主要区别
| 维度 | Docker | Podman |
|---|---|---|
| 架构 | C/S 架构,依赖 dockerd 守护进程 | 无守护进程,直接 fork/exec |
| 权限 | 默认需 root,Rootless 需额外配置 | 原生 Rootless,默认普通用户运行 |
| Pod 支持 | 需借助 Compose 或 Swarm | 原生支持 |
| K8s 集成 | 需额外工具 | 原生支持生成/运行 K8s YAML |
| 镜像构建 | 内置 docker build | 内置 + Buildah 独立构建 |
| 跨平台 | 成熟(Linux/Win/Mac) | Linux 为主,Win/Mac 需虚拟机 |
| 许可 | 桌面版对企业收费 | 完全开源免费 |
1.3 适用场景
- 生产环境 / 安全敏感场景:Rootless 和无守护进程架构降低了攻击面,适合金融、政务等对安全要求高的环境。
- Kubernetes 迁移准备:原生 Pod 支持和 K8s YAML 互转能力,让本地开发到 K8s 部署的过渡更顺畅。
- 低配服务器 / 边缘计算:无守护进程意味着更低的内存占用和更少的资源消耗。
- Red Hat 生态:RHEL/CentOS/Fedora 已将 Podman 作为默认容器引擎。
二、podman安装
官方网址:Podman
中文网址:Podman 容器工具
2.1 下载二进制包
cd /usr/local/src
# 这里下载6.1.4版本curl -fL -o podman-static-v6.1.4-linux-amd64.tar.gz \https://github.com/mgoltzsche/podman-static/releases/download/v6.1.4/podman-linux-amd64.tar.gz2.2 配置文件目录
# 创建安装目录mkdir -p /usr/local/podman/bin \ /usr/local/podman/etc/containers \ /usr/local/podman/storage \ /usr/local/podman/run/containers/storage \ /usr/local/podman/run/tmp \ /usr/local/podman/docs
# 解压二进制包cd /usr/local/src/ && tar -xzf podman-static-v6.1.4-linux-amd64.tar.gz
# 移动文件mv /usr/lcoal/src/podman-linux-amd64/usr/local/bin/* /usr/local/podman/bin/mv /usr/lcoal/src/podman-linux-amd64/usr/local/lib /usr/local/podman/libmv /usr/lcoal/src/podman-linux-amd64/usr/local/share /usr/local/podman/sharemv /usr/lcoal/src/podman-linux-amd64/etc/containers/* /usr/local/podman/etc/containers/cp /usr/lcoal/src/podman-linux-amd64/README.md /usr/local/podman/docs/README.md
# 移动quadlet,与netavark/aardvark-dns 同一搜索路径mv /usr/lcoal/src/podman-linux-amd64/usr/local/libexec/podman/quadlet /usr/local/podman/lib/podman/quadlet
# 上游自带的 storage.conf.d 把 mount_program 指向 /usr/local/bin/fuse-overlayfs(我们的目录外),# 必须删掉,否则会引用包外路径rm -rf /usr/local/podman/etc/containers/storage.conf.d2.3 修改文件属性
包里文件的 UID/GID 是构建机的 1001:1001,必须改回 root:
chown -R root:root /usr/local/podmanchmod 0755 /usr/local/podman/bin/* /usr/local/podman/lib/podman/*2.4 修改二进制名并新建一个替代
# 修改podman二进制文件名mv /usr/local/podman/bin/podman /usr/local/podman/bin/podman.real
# 新建一个名为podman的脚本cat > /usr/local/podman/bin/podman << 'EOF'#!/bin/bashPD_HOME=/usr/local/podmanC=$PD_HOME/etc/containersexport CONTAINERS_CONF=$C/containers.confexport CONTAINERS_STORAGE_CONF=$C/storage.confexport CONTAINERS_REGISTRIES_CONF=$C/registries.confexport CONTAINERS_POLICY_JSON=$C/policy.json
export XDG_CONFIG_HOME=$PD_HOME/xdg/configexport XDG_DATA_HOME=$PD_HOME/xdg/dataexport XDG_CACHE_HOME=$PD_HOME/xdg/cacheexport XDG_RUNTIME_DIR=$PD_HOME/runexport TMPDIR=$PD_HOME/run/tmp
mkdir -p "$TMPDIR" "$XDG_CONFIG_HOME" "$XDG_DATA_HOME" 2>/dev/null || truemkdir -p "$XDG_CACHE_HOME" 2>/dev/null || truechmod 0700 "$XDG_RUNTIME_DIR" "$XDG_CONFIG_HOME" 2>/dev/null || true
exec -a podman "$PD_HOME/bin/podman.real" "$@"EOF
# 修改文件权限chmod 0755 /usr/local/podman/bin/podman为什么要多这一层:podman 的配置、helper、临时目录都要靠 CONTAINERS_* 环境变量指向包内。如果用户从非登录 shell(cron、systemd、ssh host cmd、容器内 exec)调用,/etc/profile.d 不会被加载,podman 就会去 /etc/containers 和系统默认路径找依赖,直接失败。启动器把环境变量固化下来,保证任何调用方式结果一致。
文件参数说明:
exec -a podman:把argv[0]改成podman,否则podman --version会显示成podman.real version 6.1.4。XDG_*三个变量:防止在~/.config/containers、~/.cache/containers、/run/user/0/crun生成文件。TMPDIR:防止临时文件落到/tmp。
环境变量 作用 不设会怎样 CONTAINERS_CONF指定主配置 读 /etc/containers/containers.conf,配置全部失效CONTAINERS_STORAGE_CONF指定存储配置 镜像存到 /var/lib/containers/storageCONTAINERS_REGISTRIES_CONF指定镜像源配置 直连 docker.io,拉取超时 CONTAINERS_POLICY_JSON指定签名策略文件 podman pull直接报no policy.json file foundXDG_CONFIG_HOME配置目录 生成 ~/.config/containersXDG_DATA_HOME数据目录 生成 ~/.local/share/containersXDG_CACHE_HOME缓存目录 生成 ~/.cache/containersXDG_RUNTIME_DIR运行时目录 crun 状态落到 /run/user/0/crunTMPDIR临时目录 写 /var/tmp最后一行
exec -a podman ...中的-a podman是用来修正进程名的:二进制改名成podman.real后,podman --version会显示成podman.real version 6.1.4,加上这个参数后显示正常。
2.5 编写配置文件
配置文件全部放在 /usr/local/podman/etc/containers/
2.5.1 containers.conf
cat > /usr/local/podman/etc/containers/containers.conf << 'EOF'[engine]# OCI 运行时:使用包内自带的 crunruntime = "crun"
# # 容器监控进程 conmon(必须在包内)conmon_path = ["/usr/local/podman/lib/podman/conmon"]
# 辅助二进制目录:netavark / aardvark-dns / catatonithelper_binaries_dir = ["/usr/local/podman/lib/podman"]
# # 锁文件写入存储目录,避免占用 /dev/shmlock_type = "file"
# 无 systemd 环境使用 cgroupfs 直接管理 cgroupcgroup_manager = "cgroupfs"
# 事件日志写文件,不依赖 journaldevents_logger = "file"
# 临时目录收进包内,避免写 /var/tmp 与 /tmptmp_dir = "/usr/local/podman/run/tmp"
[engine.runtimes]crun = ["/usr/local/podman/bin/crun"]runc = ["/usr/local/podman/bin/runc"]
[network]# podman 5 起默认使用 netavark 网络栈network_backend = "netavark"
# netavark 2.x 只支持 nftables 防火墙后端firewall_driver = "nftables"
# 容器网段(避开 docker 默认的 172.17.0.0/16)default_subnet = "10.88.0.0/16"
[containers]# seccomp 规则文件收进包内seccomp_profile = "/usr/local/podman/etc/containers/seccomp.json"EOF关键项解释:
| 配置项 | 作用 |
|---|---|
conmon_path | 必须显式指定。helper_binaries_dir 对 conmon 无效,conmon 有独立的搜索列表,不设就会去 /usr/libexec/podman/conmon 等系统路径找,报 conmon not found |
helper_binaries_dir | netavark / aardvark-dns / catatonit / quadlet 的搜索目录 |
cgroup_manager = "cgroupfs" | 不依赖 systemd 的 cgroup 驱动 |
events_logger = "file" | 事件写入文件,不依赖 journald |
default_subnet = 10.88.0.0/16 | 避开Docker 默认的 172.17.0.0/16,防止docker容器网段冲突 |
firewall_driver = "nftables" | netavark 2.x 只支持 nftables 后端 |
2.5.2 storage.conf
podman 存储配置,镜像层、容器层、命名卷全部落在 /usr/local/podman 内
cat > /usr/local/podman/etc/containers/storage.conf << 'EOF'[storage]driver = "overlay"# 镜像与容器层存储根目录graphroot = "/usr/local/podman/storage"# 运行时元数据目录(容器运行期状态)runroot = "/usr/local/podman/run/containers/storage"transient_store = false
[storage.options][storage.options.overlay]mountopt = "nodev"EOF这里的 driver 必须显式写 overlay。如果沿用系统里已有旧存储库(其记录为空 driver ""),显式写 overlay 会报
database graph driver "" does not match our graph driver "overlay"。
本次是全新 graphroot,没有历史数据库,因此可以显式设置。
2.5.3 registries.conf
配置镜像源
cat > /usr/local/podman/etc/containers/registries.conf << 'EOF'unqualified-search-registries = ["docker.io", "quay.io", "ghcr.io"]
[[registry]]prefix = "docker.io"location = "docker.io"
[[registry.mirror]]location = "docker.m.daocloud.io"
[[registry.mirror]]location = "docker.1ms.run"EOF2.5.4 policy.json
保留上游原值(内网镜像站不提供签名校验,需要放开):
cat > /usr/local/podman/etc/containers/policy.json << 'EOF'{ "default": [{ "type": "insecureAcceptAnything" }], "transports": { "docker-daemon": { "": [{ "type": "insecureAcceptAnything" }] } }}EOF2.6 配置环境变量
cat > /etc/profile.d/podman.sh <<'EOF'if [ -d /usr/local/podman/bin ]; then case ":${PATH}:" in *:/usr/local/podman/bin:*) ;; *) PATH="/usr/local/podman/bin:${PATH}" ;; esac export PATH
C=/usr/local/podman/etc/containers export CONTAINERS_CONF=$C/containers.conf export CONTAINERS_STORAGE_CONF=$C/storage.conf export CONTAINERS_REGISTRIES_CONF=$C/registries.conf export CONTAINERS_POLICY_JSON=$C/policy.jsonfiEOFsource /etc/profile用 if [ -d ... ] 包住:目录被删后脚本即使残留也不会污染 PATH。
2.7 测试podman
podman --version
# 首次执行 info 会创建 overlay 存储库podman info
# 查看依赖路径podman info 2>&1 | grep -iE 'graphRoot|graphDriverName|runRoot|networkBackend|ociRuntime|conmon'
# 拉取镜像测试podman pull hello-world
podman run --rm hello-world2.8 卸载podman
# 删除目录rm -rf /usr/local/podman
# 删除环境变量rm -f /etc/profile.d/podman.sh
# 镜像 blob 校验缓存/var/lib/containers/cache三、podman使用
Podman 的命令行和 Docker 几乎一样,大多数时候把 docker 直接换成 podman 就能用。 它最大的区别是无守护进程、默认支持 rootless,所以更适合在 Linux 上以普通用户管理容器。
3.1 常用命令速查
| 功能 | 命令 | 说明 |
|---|---|---|
| 查看版本 | podman version | 确认安装是否成功 |
| 搜索镜像 | podman search nginx | 从仓库搜索镜像 |
| 拉取镜像 | podman pull nginx:1.27 | 建议使用固定版本标签 |
| 查看镜像 | podman images | 列出本地镜像 |
| 运行容器 | podman run -d --name web -p 8080:80 nginx:1.27 | 后台启动容器 |
| 查看容器 | podman ps -a | 列出所有容器 |
| 查看日志 | podman logs -f web | 实时查看日志 |
| 进入容器 | podman exec -it web bash | 在容器内执行命令 |
| 停止/启动 | podman stop web / podman start web | 生命周期管理 |
| 删除容器 | podman rm web | 删除已停止容器 |
| 删除镜像 | podman rmi nginx:1.27 | 删除本地镜像 |
| 复制文件 | podman cp ./index.html web:/usr/share/nginx/html/ | 主机和容器互传文件 |
| 监控资源 | podman stats web | 查看 CPU、内存等 |
| 清理资源 | podman system prune | 清理无用镜像、容器、网络 |
podman info # 环境详情
podman volume create data # 命名卷
podman run -d -v data:/usr/share/nginx/html nginx # 挂载卷
podman volume ls # 卷列表
podman system df # 空间占用
podman system prune -a # 清理未使用资源
podman system reset -f # 清空全部镜像/容器/卷(危险)
podman generate kube web > web.yaml # 导出为 K8s YAML
podman play kube web.yaml # 从 YAML 启动
podman pod create --name mypod -p 8080:80 # Pod3.2 使用示例
3.2.1 基础用法
# 运行容器podman run -d --name web -p 8080:80 --restart=always nginx:1.27
# 查看容器运行状态podman ps -a
# 查看镜像podman images
# 查看日志podman logs -f web
#进入容器podman exec -it web bash
# 停止容器并删除podman stop webpodman rm web
# 删除镜像podman rmi nginx:1.273.2.2 挂载目录
mkdir -p data/wwwecho "<h1>Hello Podman</h1>" > data/www/index.html
# :Z 独占标签。将该目录的标签设为仅此容器可访问,并递归修改宿主机上该目录及其内容的 SELinux 上下文# :z 共享标签。标签允许多个容器访问,同样递归修改# 系统没有启用 SELinux时,该标签可以省略podman run -d --name web -p 8080:80 -v data/www:/usr/share/nginx/html:Z nginx:1.273.2.3 容器携带变量
# 启动容器使用变量、同时使用命名卷pgdata,podman run -d --name db \-e POSTGRES_PASSWORD=example \-p 5432:5432 \-v pgdata:/var/lib/postgresql/data \postgres:16
# 查看容器状态podman pspodman logs -f db
# 进入数据库podman exec -it db psql -U postgres3.2.4 使用pod模拟容器
Podman 的 Pod 类似 Kubernetes 的 Pod,多个容器可以共享网络。
# 创建一个podpodman pod create --name app -p 8080:80
# 在pod中启动容器podman run -d --pod app --name web nginx:1.27podman run -d --pod app --name redis redis:alpine
# 查看podpodman pod ps
# 停止podpodman pod stop app
# 删除podpodman pod rm app3.2.4.1 Nginx 反向代理 + 后端 API
后端不需要暴露给宿主机,只让 Nginx 对外服务。
podman pod create --name api-pod -p 8080:80
podman run -d --pod api-pod --name backend php:latest
podman run -d --pod api-pod --name nginx \-v ./nginx.conf:/etc/nginx/nginx.conf:Z \nginx:alpine3.2.4.2 ELK / 日志栈本地调试
把 Elasticsearch、Logstash、Kibana 放进一个 Pod,内部访问非常简单。
podman pod create --name elk -p 5601:5601
podman run -d --pod elk --name elasticsearch \-e "discovery.type=single-node" \-v es-data:/usr/share/elasticsearch/data \elasticsearch:8.17.0
podman run -d --pod elk --name logstash \logstash:8.17.0
podman run -d --pod elk --name kibana \-e "ELASTICSEARCH_HOSTS=http://localhost:9200" \kibana:8.17.0Kibana 和 Logstash 访问 Elasticsearch 时都可以直接用 localhost:9200。
3.2.4.3 共享数据卷:构建产物 + 静态服务
podman volume create build-data
podman pod create --name build-pod -p 8080:80
podman run -d --pod build-pod --name builder \-v build-data:/app/dist \node:20 \sh -c "cd /app && npm run build"
podman run -d --pod build-pod --name web \-v build-data:/usr/share/nginx/html:Z \nginx:alpine这样可以把构建输出和静态服务拆成两个容器,但通过同一个卷共享文件。
3.2.4.4 限制整个pod资源
资源限制可以加在 Pod 上,Pod 内所有容器共享这些限制。
podman pod create \--name limited-pod \-p 8080:80 \--memory=2g \--cpus=2
podman run -d --pod limited-pod --name app myapp:latestpodman run -d --pod limited-pod --name worker worker:latest3.2.4.5 用YAML管理 Pod
# 本地 Pod 导出成 YAMLpodman generate kube mypod > mypod.yaml
# 使用yaml启动podman play kube mypod.yaml3.2.4.6 用systemd管理 Pod
podman pod create --name webapp -p 8080:80
podman run -d --pod webapp --name web nginx:alpine
podman generate systemd --name webapp --files --new生成后把 service 文件放到:
- 用户级:
~/.config/systemd/user/ - 系统级:
/etc/systemd/system/
然后:
systemctl --user daemon-reloadsystemctl --user enable --now pod-webapp.service如果想让普通用户的服务开机也能运行,还需要执行:
loginctl enable-linger文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!




























