Podman安装和使用

Podman install and Setting

Podman无守护进程且默认rootless,当下较好的平替

Podman是一种无守护进程、开源的Linux原生容器引擎,旨在使用开放容器倡议(OCI)的容器和容器镜像来查找、运行、构建、共享和部署应用程序,它由Red Hat团队开发,提供了与Docker兼容的命令行界面,并支持在无需root权限的“rootless”模式下运行容器,以提高安全性.

1. 历史背景和特点

  1. 诞生契机与早期背景(2016-2018)
  • 从调试工具起步:Podman 最初并非作为独立的容器引擎设计,而是由 Red Hat 的工程师在 2016 年开发 CRI-O(Kubernetes 的轻量级容器运行时)时,为了辅助调试而萌生的工具

  • 正式开源:2017 至 2018 年间,Podman 作为 Red Hat 旗下的项目正式开源(首个公开版本 v0.2 于 2018 年 2 月发布),并确立了“无守护进程(Daemonless)”和“无根模式(Rootless)”两大核心特性

2018年初:Podman 1.0 正式发布,主打 daemonless 架构

注记
  • Docker(2013) 把容器从内核功能(Linux namespaces + cgroups)包装成开发者可用的 image + run 命令,开启了容器时代

  • OCI(2015) 把容器格式标准化,让任何工具都能跑别人的镜像

  1. 爆发与成熟(2019 至今)
  • 商业许可调整带来的契机:2019 年,Docker 调整了企业版(Docker EE)的许可策略,促使大量企业寻找免费且安全的替代方案,Podman 因此获得了爆发式增长

  • 2019年:RHEL 8 将 Podman 作为默认容器工具,移除 Docker

  • 2020年:Podman 2.0 发布,引入 REST API 和 Docker API 兼容层

  • 2021年:Podman 3.0 发布,增强网络功能(netavark)

  • 2022年:Podman 4.0 发布,原生支持 Podman Compose

  • 2023年:Podman 4.5+ 强化 Kubernetes YAML 支持

  • 2024年:Podman 5.0 发布,性能与安全性进一步优化

  • 2026年: Podman 6.0发布,网络基础设施的现代化,同时Podman Desktop 桌面版也有了稳定版

  1. 核心特征
  • 无守护进程架构:无需常驻后台进程,降低系统资源占用
  • 原生 Rootless 支持:普通用户即可运行容器,提升安全性
  • OCI 标准兼容:完全兼容 Docker 镜像格式
  • Pod 原生支持:支持 Kubernetes Pod 概念
  • systemd 深度集成:可直接生成 systemd 服务单元
  • 强安全模型:支持 SELinux、User Namespace、cgroup v2
  • API 兼容层:可替代 Docker daemon(podman-docker)

2. 核心架构与技术原理

Podman 与 Docker 都是遵循 OCI(开放容器倡议)标准的容器化工具,底层都利用了 Linux 内核的 Namespace(资源隔离)、Cgroups(资源限制)和 UnionFS(联合文件系统)来实现轻量级虚拟化。然而,两者在核心架构和技术原理上存在显著差异

对比维度 Docker Podman
架构模式 C/S 架构,依赖 dockerd 守护进程 无守护进程,直接调用 OCI 运行时
默认权限 默认需 root 权限 原生支持 Rootless(普通用户权限)
单点故障 守护进程崩溃导致所有容器失控 容器独立运行,互不影响
空闲资源占用 较高(需维持守护进程) 极低(无常驻进程)
K8s 兼容性 需借助 Swarm 或外部工具 原生支持 Pod 概念,支持 K8s YAML 互转
跨平台支持 极佳(Linux/Windows/macOS) 以 Linux 为主,Win/Mac 依赖虚拟机
适用场景 本地开发、跨平台环境、成熟生态依赖 生产环境、高安全需求、K8s 迁移、边缘计算
  1. Docker客户端-守护进程架构
  • Docker Client(客户端):相当于顾客(或服务员)。当你在终端输入 docker run 或 docker ps 等命令时,你就是在向系统“点餐”。客户端本身并不负责做菜(运行容器),它只负责把你的需求(指令)翻译成 API 请求,发送给后台

  • Docker Daemon / dockerd(守护进程):相当于餐厅的后厨(主厨)。它是一个一直在后台默默运行的服务程序。它接收到客户端的请求后,负责真正去执行这些操作(如拉取镜像、创建容器、分配网络等),并把结果返回给客户端

常驻后台的守护进程意味着资源的占用,就像煮面锅一直要开着一样

守护进程意味着需要root权限

  • 统一调度与管理:后厨(Daemon)需要统筹管理所有的食材(镜像)、正在做的菜(运行中的容器)以及厨房设备(网络和存储)。如果没有一个统一的调度中心,所有的操作就会乱套

  • 持续监控与状态维护:厨房必须一直开着,即使现在没有客人点餐。dockerd 需要持续在后台监控容器的状态,比如某个容器崩溃了需要重启,或者容器运行结束后需要清理资源

  • 集中处理请求:不管你是通过命令行(CLI)、图形界面还是外部程序发起请求,所有的请求都会统一发送给 dockerd 来处理,保证了系统的一致性

docker architecture

理解了docker守护进程和客户端的关系,就能理解为什么docker需要root权限,为什么守护进程崩溃会导致docker故障,所以podman逐渐分割了docker的蛋糕

  1. Daemonless 的技术实现
  1. Podman 抛弃了 C/S 架构,采用 Linux 原生的 fork-exec 模型
  • 直接调用:Podman CLI 不需要经过中央守护进程,而是直接调用底层的 OCI 运行时(如 runc 或 crun)来创建和启动容器
  • 独立生命周期:每个容器都是一个独立的系统进程,由系统 init 进程(如 systemd)托管。这意味着即使某个容器崩溃,也绝不会影响其他容器,彻底消除了单点故障风险

在 Linux 系统中,fork-exec 是一种非常经典的进程创建方式。Podman 正是利用了这个系统底层的机制来管理容器

  • Fork(复制):当你执行 podman run 时,Podman 主进程会调用 fork() 系统调用,像细胞分裂一样,复制出一个和自己一模一样的“子进程”
  • Exec(替换):这个新生的子进程会立刻调用 exec() 系统调用,将自己原本的代码替换为真正的容器运行时程序(比如 runc 或 crun),从而启动真正的容器进程

Podman CLI 不需要经过中央守护进程,而是直接调用底层的 OCI 运行时(如 runc 或 crun)来创建和启动容器

  1. 核心机制
  1. Podman 命令直接调用 libpod 库
  2. libpod 通过 OCI Runtime(runc/crun)启动容器
  3. 容器进程成为 Podman 的子进程
  4. 退出后容器进程由 conmon 监控(Podman 4.0+ 默认)

runc 的工作流程严格遵循 OCI 运行时规范,整个过程不依赖外部守护进程,完全以 fork-exec 模型在用户态完成。其核心启动流程如下:

  • Fork(创建子进程):当执行 runc create 或 runc start 时,runc 主进程(parent)首先通过 fork() 创建一个子进程(child)
  • 环境配置(Namespace 与 Cgroups):子进程(runc init)开始准备用户进程的运行环境。它通过调用 clone() 系统调用并指定 CLONE_NEW* 标志,启用 PID、UTS、NET、USER 等命名空间
  • Exec(替换进程):环境配置完成后,子进程使用 execve() 系统调用,将自己替换为用户定义的命令(如 /bin/sh 或 /sbin/init)。至此,子进程变身为容器内的首个进程(init 进程),容器正式启动
注记

libpod 是一个用于容器生命周期管理的底层核心库,它是整个 Podman 容器引擎的基石,libpod 是一个用 Go 语言编写的核心代码库

libpod 为 Podman 提供了底层的 API 接口,负责管理容器、Pod(容器组)、容器镜像以及挂载卷等核心对象。它支持多种容器镜像格式(如 OCI 和 Docker 格式),并全面接管了容器的生命周期(包括创建、运行、检查点恢复、移除等)以及网络管理

  • Podman CLI 是“前台服务员”(负责接待顾客、记录点单)
  • libpod 是“后厨主厨”(负责统筹调度、准备食材、安排工序)
  • conmon 是“专属传菜员/监控员”(负责盯着这道菜、传递热气)
  • runc/crun 是“底层厨师”(负责真正开火炒菜)
[用户输入: podman run nginx]


[Podman CLI] ──(1. 解析命令)──> [registry.ContainerEngine()] ──(2. 直接函数调用)──> [libpod]

                                                                            │ (3. 准备 config.json)
                                                                            │ (4. fork-exec)

3. 何时选择podman

优先选择Podman:

  • 生产环境服务器(安全性要求高)
  • Rootless 容器场景
  • systemd 管理容器服务
  • CI/CD 镜像构建(无需 daemon)
  • Kubernetes 迁移准备

优先选择 Docker 的场景

  • 本地开发与跨平台环境:如果您需要完善的跨平台支持(Windows、macOS、Linux),或者依赖 Docker Compose 进行多容器应用的本地开发与测试,Docker 是主流选择
  • 团队协作与快速迭代:Docker 拥有极其完善的生态系统和庞大的社区支持,新人上手快、培训成本低。遇到各类问题都能在社区迅速找到解决方案,非常适合需要快速迭代和降低沟通成本的团队

4. 安装与环境配置

4.1 Linux

sudo pacman -S podman

sudo apk add podman

sudo dnf -y install podman

sudo apt-get -y install podman

# Ubuntu 20.10 and newer
sudo apt-get update
sudo apt-get -y install podman

Ubuntu中,Ubuntu22.04默认的Podman版本是3.4.4,Ubuntu24.04中Podman默认版本是4.9.3,Ubuntu20.04中没有更新镜像源的话是无法安装Podman,Ubuntu 20.04 的默认内核为 5.4,官方推荐在此内核下配合 Podman 3.4+ 使用

  1. 首先加载系统的环境变量,获取当前系统的版本号

cat /etc/os-release

  1. 添加 Podman 的 APT 软件源,将 Kubic 项目的稳定版软件源地址写入到系统的源列表中
echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_20.04/ /" | sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
  1. 导入软件源的 GPG 公钥,下载并添加该源的签名密钥,以确保软件包的安全性
curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${VERSION_ID}/Release.key | sudo apt-key add -
  1. 更新包索引并安装 Podman
sudo apt-get update
sudo apt-get install -y podman

4.2 MacOS

容器强依赖于 Linux 内核的 Namespace 和 Cgroups 特性。因为 macOS 的底层是 Darwin 内核,它本身无法直接运行 Linux 容器。因此,Podman 在 macOS 上的第一步,就是必须提供一个真正的 Linux 环境

为了解决 macOS 无法原生运行容器的问题,Podman 引入了 podman machine 机制

  • 轻量级虚拟机:Podman Machine 本质上是一个内嵌的、轻量级的 Linux 虚拟机(通常基于 Fedora CoreOS)。
  • 原生虚拟化加速:在 macOS 上,这个虚拟机并不是通过笨重的第三方软件(如 VirtualBox)运行的,而是利用了 macOS 原生的虚拟化框架(如 Apple 的 HVF 或 LibKrun 提供程序)来实现硬件级加速,从而保证极高的性能

按照系统推荐,去https://podman.io/官网进行下载即可,不推荐使用Homebrew安装

安装完成后,创建和启动第一个Podman machine:

podman machine init
podman machine start

# Verify the installation information
podman info

4.3 Windows

容器强依赖于 Linux 内核的 Namespace 和 Cgroups 特性。因为 Windows 的底层是 NT 内核,无法直接运行 Linux 容器。因此,Podman 在 Windows 上的第一步,就是必须提供一个真正的 Linux 环境

  • WSL2 虚拟化:Podman 巧妙地利用了 Windows 原生的 WSL2(Windows Subsystem for Linux 2)作为底层虚拟化平台。WSL2 内部运行着一个完整的、真正的 Linux 内核实例,作为容器的真正宿主机
  • 与传统的笨重虚拟机不同,WSL2 利用 Hyper-V 驱动实现了快速启动,在文件系统和网络性能上非常接近原生 Linux 环境

这种情况下,对应着两种使用Podman的方式

  • 在 Windows 原生环境使用(PowerShell / CMD):在 Windows 终端里敲下 podman run 时,Windows 上的 Podman CLI 只是一个客户端。它会通过底层的通信机制,将指令远程转发给运行在 WSL2 虚拟机内部的 Podman 服务

  • 直接在wsl2中进行操作

5. Rootless 容器详解

Rootless 容器允许普通用户在无 root 权限的情况下运行容器,这是 Podman 最重要的安全特性之一

  1. 检查Rootless状态
# 查看当前运行模式
podman info | grep -i rootless

# 输出示例:
# rootless: true
  1. 检查配置UID/GID

Podman 的核心安全机制——Rootless(无根)模式有关。为了让普通用户(非 root)也能安全地运行容器,Podman 依赖 Linux 内核的 User Namespace(用户命名空间) 技术。这种技术需要将容器内的 UID/GID 映射到宿主机上的一段专属 ID 范围

Rootless 模式依赖 /etc/subuid 和 /etc/subgid 这两个配置文件。如果当前用户没有在这个文件中被分配 ID 范围,Podman 就无法创建用户命名空间

cat /etc/subuid
cat /etc/subgid

# 如果缺失
# 为用户分配 65536 个子 UID
sudo usermod --add-subuids 100000-165535 $USER

# 为用户分配 65536 个子 GID
sudo usermod --add-subgids 100000-165535 $USER
  1. Cgroup设置

Cgroup(Control Groups,控制组)是 Linux 内核提供的一种底层机制,专门用于对一组进程所使用的物理资源进行限制、记录、隔离和控制

如果把 Namespace 比作给容器划分了“独立的房间”,那么 Cgroup 就是给每个房间安装的“电表、水表和限流阀”,用来规定这个房间最多能用多少资源。如果没有 Cgroup 的限制,某个容器可能会疯狂占用 CPU 或内存,直接把整个宿主机拖垮

  • 内存限制(Memory)
  • CPU 限制(CPU)
  • 磁盘 I/O 限制(Blkio)
  • 进程数限制(Pids)
stat -fc %T /sys/fs/cgroup/
# cgroup2fs → cgroup v2(支持 Rootless)
# tmpfs → cgroup v1(不完全支持 Rootless)

6. 镜像管理和配置文件

6.1 镜像源配置文件

registries.conf 是 Podman 的容器镜像注册表(Registry)配置文件,它的核心作用是告诉 Podman:当用户输入一个不包含仓库地址的“短名称”镜像时,应该去哪些仓库里搜索

当你只输入 podman pull nginx 时,Podman 不知道 nginx 到底在哪个服务器上。它会读取 registries.conf 中配置的搜索列表(例如 docker.ioquay.io),然后按顺序去这些仓库里找 nginx 镜像

不同的路径代表Podman 配置文件的不同层级和作用范围。它们的核心区别在于:生效范围(全局 vs 个人)、修改权限以及优先级

  1. 系统级配置(全局生效,需 Root 权限)

这两个文件属于系统级配置,主要影响所有用户,通常需要管理员(Root)权限来修改

  • /etc/containers/registries.conf (系统级主配置)
    • 作用:这是 Podman 的全局默认配置。它定义了系统范围内所有用户共享的默认镜像源、搜索列表等
    • 特点:它是所有用户的基础配置。如果某个普通用户没有自己的配置文件,就会默认使用这里的规则
  • /etc/containers/registries.conf.d/*.conf(系统级覆盖配置)
    • 作用:这是一个扩展配置目录。管理员可以在这里放置多个 .conf 文件,作为对主配置文件的补充或覆盖
    • 特点:它的优先级高于主配置文件 /etc/containers/registries.conf。这种设计非常灵活,比如系统管理员想单独为某个私有仓库添加配置,只需在这个目录下新建一个文件即可,而不用去修改庞大的主配置文件
  1. 用户级配置(个人生效,普通用户可用)
  • ~/.config/containers/registries.conf(用户级配置)
    • 这是当前用户的专属配置
    • 特点:它的优先级最高。只要这个文件存在,Podman 就会优先读取它,并且会完全覆盖掉前面提到的两个系统级配置。普通用户无需 Root 权限即可创建和修改

常见的配置方式

# /etc/containers/registries.conf

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

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

[[registry.mirror]]
location = "docker.m.daocloud.io"

[[registry.mirror]]
location = "dockerproxy.net"

镜像还是不稳定的,后续可以搭建自己的私有仓库

  1. 自建私有镜像仓库设置

自建镜像私有仓库,是指在你自己控制的服务器或内网环境中部署一套容器镜像存储服务,用于替代 Docker Hub 等公共仓库,实现镜像的私有存储、分发和管理

场景 说明
企业内部分发 团队/CI/CD 从内网拉取镜像,速度快、不受公网限制
安全合规 敏感代码/基础镜像不出外网,满足审计要求
离线/隔离环境 生产网络无法访问互联网时,作为唯一镜像源
镜像缓存加速 代理缓存 Docker Hub,首次拉取后本地缓存,后续秒级响应
版本管控 统一管理内部镜像标签、签名、漏洞扫描
[[registry]]
location = "docker.io"
prefix = "docker.io"
location = "registry.mycompany.local"  # 直接把目的地换成公司内网仓库

当你执行 podman pull docker.io/nginx 时,Podman 根本不会去访问真正的 docker.io,而是直接去 registry.mycompany.local 拿货。这通常用于完全断网的企业内网环境

# ---------- 私有仓库(按需取消注释)----------
# [[registry]]
# location = "registry.mycompany.local:5000"
# insecure = true    # 纯内网 HTTP 仓库设为 true,HTTPS 仓库删除此行

6.2 挂载和安全设置

在 Podman 中,mounts.conf 配置文件主要用于在执行podman runpodman build 命令时,自动将主机上的特定目录内容复制到容器内部

出于安全考虑,mounts.conf 的挂载不是传统的直接绑定挂载(bind mount)。它会将主机源目录中的内容复制到容器的存储中,而不是让容器直接链接到主机的路径上

在 Podman 中,seccomp.json 文件主要用于定义容器内部允许或禁止执行的 Linux 系统调用(syscalls)的白名单规则。容器与宿主机共享同一个 Linux 内核。为了防止恶意程序或漏洞利用通过危险的系统调用破坏宿主机,Podman 利用这个 JSON 文件来限制容器进程能调用的内核接口。它会拦截并过滤系统调用,只放行白名单内的安全调用。

这些podman都有默认的文件参数

7. 镜像的控制和操作

角色 它是什么 类比
仓库 (Registry) 镜像的存储和分发中心 图书馆 / App Store
镜像 (Image) 创建容器的只读模板 图书馆里的一本书(只读,你不能改)
容器 (Container) 镜像的运行实例 你借出来正在读的那本书(可以在上面做笔记)
Podman 管理以上三者的工具 图书馆管理员

7.1 镜像的基础操作

  1. 拉取镜像

# 拉取最新版本
podman pull nginx

# 拉取指定版本
podman pull nginx:1.25-alpine

# 拉取指定架构镜像
podman pull --platform=linux/arm64 nginx

# 从私有仓库拉取
podman pull registry.example.com:5000/myapp:v1.0
选项 说明 使用示例
--all-tags 拉取该仓库下所有带标签的镜像 podman pull --all-tags nginx
--arch ARCH 指定目标 CPU 架构(如 arm64 podman pull --arch arm64 nginx
--authfile PATH 指定认证文件路径(也可用 REGISTRY_AUTH_FILE 环境变量) podman pull --authfile /path/to/auth.json nginx
--cert-dir PATH 指定包含 TLS 证书和密钥的目录 podman pull --cert-dir /etc/certs nginx
--creds USER:PASS 指定私有仓库的用户名和密码 podman pull --creds admin:secret123 registry.example.com/myapp
--os OS 指定目标操作系统(如 linux podman pull --os linux nginx
--platform STRING 指定完整目标平台(与 --arch/--os 互斥) podman pull --platform linux/arm64 nginx
--variant STRING 指定架构变体(如 ARM v7/v8 podman pull --arch arm --variant v8 nginx
-q, --quiet 静默模式,仅输出镜像 ID podman pull -q nginx
--tls-verify 强制 HTTPS 并验证证书(默认 true podman pull --tls-verify=false 192.168.1.100:5000/myapp
--disable-content-trust Docker 兼容选项,Podman 中无实际作用(NOOP) 无需使用
  1. 查看镜像
命令 核心功能 常用参数 / 示例 适用场景
podman images 列出本地所有镜像 podman images nginx (按名称过滤)
podman images -q (仅输出镜像ID)
podman images --filter dangling=true (查悬空镜像)
日常查看本地有哪些镜像,或用于脚本批量操作
podman inspect 查看镜像底层元数据 podman inspect nginx:latest
podman inspect -f "{{.Config.Cmd}}" nginx (提取默认启动命令)
排查镜像配置问题,查看环境变量、暴露端口、存储驱动等
podman history 查看镜像构建历史 podman history nginx:latest
podman history --no-trunc nginx (显示完整命令)
追溯镜像是如何一步步构建的,排查安全隐患或镜像体积过大问题
podman image tree 树状展示镜像层级 podman image tree nginx:latest 直观查看镜像的分层结构(Layer hierarchy)及每层大小
podman image diff 查看镜像文件变更 podman image diff nginx:latest 检查镜像相对于其父镜像,新增(A)、修改(C)或删除(D)了哪些文件
podman image exists 检查镜像是否存在 podman image exists nginx:latest 用于 Shell 脚本中判断镜像是否已下载(存在返回 0,不存在返回 1)
podman image prune 清理无用镜像 podman image prune (清理悬空镜像)
podman image prune -a (清理所有未被容器使用的镜像)
释放磁盘空间,清理废弃或构建失败的中间层镜像

镜像的详细信息非常的多和复杂,可以让AI进行辅助

  1. 镜像的标签与推送

标签的作用相当于做了一次当前的镜像,为了留档,方便出错的时候回档,tag打标签主要还是为了给私有仓库的推送,或者把修改好的镜像推送到远程共享仓库

  1. 现在服务器上创建Registry 存储目录
sudo mkdir -p /opt/my-registry
  1. 启动Registry 镜像
podman run -d \
  --name my-registry \
  --restart=always \
  -p 5000:5000 \
  -v /opt/my-registry:/var/lib/registry \
  docker.io/library/registry:2
  • -d:后台运行容器
  • --name my-registry:为容器指定名称
  • --restart=always:设置容器在启动失败时自动重启
  • -p 5000:5000:将容器的5000端口映射到主机的5000端口
  • -v /opt/my-registry:/var/lib/registry:将主机的/opt/my-registry目录挂载到容器的/var/lib/registry目录,用于存储镜像
  • docker.io/library/registry:2:使用registry镜像的2版本

运行之后输入podman ps来查看是否运行,能看到

CONTAINER ID   IMAGE                         PORTS
xxxx           docker.io/library/registry:2  0.0.0.0:5000->5000/tcp
  1. my.company解析到你的Registry 服务器, 如果只是公司内网使用,最开始可以先不用 HTTPS, Podman默认会使用HTTPS所以需要设置这个 Registry 是 insecure registry,可以使用 HTTP

域名对应上IP是为了安全和简化传输,把域名使用DNS 或 /etc/hosts 会负责找到服务器

/etc/hosts中添加xxx.xxx.xxx.xx my.company,这个过程不需要访问互联网,也不需要购买域名,只是一个内部自定义主机名

  1. 在 Podman 中配置 insecure registry

sudo vim /etc/containers/registries.conf.d/my-company.conf,然后输入

[[registry]]
location = "my.company:5000"
insecure = true

表示不需要进行https认证,然后直接尝试podman login my.company:5000,输入你的现在登陆的名字和密码即可完成登陆

  1. 给镜像重新打标签
podman tag \
  community.wave.seqera.io/library/multiqc:1.34--db7c73dae76bc9e6 \
  my.company:5000/multiqc:1.34

这里没有复制镜像,也没有重新下载

原来的镜像:
community.wave.seqera.io/library/multiqc:1.34--db7c73dae76bc9e6

                         │ podman tag

私有仓库镜像:
my.company:5000/multiqc:1.34
  1. 推送到私有Registry
podman push my.company:5000/multiqc:1.34

Podman 会把镜像上传到你刚才搭建的 Registry,推送成功后,可以检查curl http://pigeon.company:5000/v2/_catalog

# 打标签
podman tag nginx:latest myregistry.com/nginx:v1.0

# 推送到远程仓库
podman push myregistry.com/nginx:v1.0

# 推送时登录
podman login myregistry.com
podman push myregistry.com/nginx:v1.0
  1. 删除镜像
# 删除单个镜像
podman rmi nginx

# 强制删除(即使有容器使用)
podman rmi -f nginx

# 删除所有未使用镜像
podman image prune

# 删除所有镜像
podman rmi -a

7.2 容器的操作

下面查看一下基础的运行命令,当你从仓库拉去下来镜像,接下来就该运行镜像让它形成一个容器运行,表示启动

podman run --name basic_httpd -d -p 8080:80/tcp docker.io/nginx
  1. 基础运行容器

# 前台运行
podman run nginx

# 后台运行
podman run -d nginx

# 指定容器名称
podman run -d --name web nginx

# 自动删除(退出后删除容器)
podman run --rm alpine echo "hello"
  1. 端口映射
# 单端口映射
podman run -d -p 8080:80 nginx

# 多端口映射
podman run -d -p 8080:80 -p 8443:443 nginx

# 绑定到指定 IP
podman run -d -p 192.168.1.10:8080:80 nginx

# 随机端口映射
podman run -d -P nginx
  1. 容器资源限制

# 限制内存
podman run -m 512m nginx

# 限制 CPU
podman run --cpus=2 nginx

# CPU 配额(20% CPU)
podman run --cpu-quota=20000 nginx

# 限制 I/O
podman run --device-read-bps /dev/sda:1mb nginx
  1. 容器查看和监控
# 查看运行中的容器
podman ps

# 查看所有容器(包括停止的)
podman ps -a

# 查看容器详细信息
podman inspect web

# 查看容器资源使用情况
podman stats

# 查看容器日志
podman logs web

# 实时跟踪日志
podman logs -f web

# 查看最近 100 行日志
podman logs --tail 100 web

容器停止后依然会占用名称,但是几乎不占用系统资源, 这主要取决于区分“逻辑占用”和“物理占用”:

  • 逻辑占用:名称依然被保留。在 Podman 中,容器的名称是全局唯一的标识符。即使容器已经停止(Exited),它的元数据(包括名称、ID、创建时间等)仍然保存在本地存储中,并不会自动消失

  • 物理占用:几乎不消耗系统资源。CPU/内存:容器停止后,其内部进程全部终止,不再消耗 CPU 和内存

# 先删除已有容器
podman rm basic_httpd

# 再重新运行
podman run --name basic_httpd -d -p 8080:80/tcp docker.io/nginx

podman inspect 是一个用于查看容器、镜像、网络、卷、Pod 等对象的底层详细信息的命令,输出格式为 JSON

podman ps 只能看到容器的”表面信息”(ID、名称、状态、端口等),而 podman inspect 则能看到它的”全部底牌”

# 查看容器的网络配置
podman inspect basic_httpd | grep IPAddress
podman inspect --format '{{.NetworkSettings.IPAddress}}' basic_httpd

# 查看容器的挂载卷信息
podman inspect basic_httpd | grep -A 10 Mounts

podman stats实时监控一个或多个容器的资源使用情况,输出类似 Linux 的 top 命令,但针对的是容器维度

对比维度 cgroup v1 cgroup v2
层级结构 多棵树,每子系统独立 一棵统一树
挂载点 多个(/sys/fs/cgroup/cpu/sys/fs/cgroup/memory…) 单一(/sys/fs/cgroup
进程归属 可同时属于多个 cgroup 只能属于一个 cgroup
线程级控制 ❌ 不支持 ✅ 支持
内存统计 kmem 单独算,口径不一致 统一核算,OOM 更准确
PSI 压力指标 ❌ 不支持 ✅ 支持
默认系统 CentOS 7/8、Ubuntu 18.04 Ubuntu 22.04+、RHEL 9、Fedora 31+
K8s 支持 1.35 起不再支持 1.25+ GA 支持

v1 像是每个部门(CPU、内存、I/O)各自为政、各管一摊;v2 则是把所有部门整合到一个统一的管理体系下,规则一致、管理清晰、功能更强。对于你之前遇到的 podman stats 报错,升级到 v2 不仅能解决 rootless 模式下的统计问题,也是未来容器化环境的必然方向

podman logs 的核心用途是查看容器内部应用输出的日志(即容器主进程写到 stdout/stderr 的内容)

  1. 进入与执行命令
# 进入容器 Shell
podman exec -it web /bin/bash

# 执行单个命令
podman exec web ls /var/log

# 以 root 用户执行
podman exec --user root web apt-get update

# 在容器中运行后台进程
podman exec -d web nginx -s reload
  • -i(interactive):保持标准输入打开,让你能在容器里打字
  • -t(tty):分配一个伪终端,让界面看起来像正常的终端
  • /bin/bash:在容器内启动 bash shell。如果容器是基于 Alpine 的精简镜像(没有 bash),可以换成 /bin/sh
  • 退出时输入 exit 或按 Ctrl+D,容器继续运行不受影响
  • --user root:指定以 root 身份执行命令。很多容器默认以非 root 用户运行(安全最佳实践),但安装软件、修改系统文件时需要 root 权限
  1. 停止与删除
# 停止容器
podman stop web

# 强制停止(发送 SIGKILL)
podman stop -t 0 web

# 重启容器
podman restart web

# 删除容器
podman rm web

# 强制删除运行中的容器
podman rm -f web

# 删除所有停止的容器
podman container prune

7.3 容器储存管理和卷管理

  1. 容器的导出与导入
维度 export/import & save/load checkpoint/restore
保存内容 仅文件系统和元数据 文件系统 + 内存状态 + 进程状态 + 网络连接
恢复后 容器从头启动,内存数据清零 容器从快照点继续运行,内存数据完整保留
典型用途 备份、迁移镜像/容器 容器热迁移、故障恢复
依赖工具 无需额外工具 需要安装 CRIU(Checkpoint/Restore In Userspace)
运行模式 rootless 和 root 都支持 通常需要 root 权限
# 导出容器为 tar 文件
podman export web > web-container.tar

# 导入 tar 为镜像
cat web-container.tar | podman import - web:exported

# 保存镜像为 tar(推荐)
podman save -o nginx.tar nginx:latest

# 加载镜像
podman load -i nginx.tar
  1. 容器快照

容器快照的核心用途可以概括为四个词:备份、恢复、迁移、分发。它让你能在某个时间点”冻结”容器的状态,之后随时回退或复制

Podman 调用底层 OCI 运行时(runc/crun),由运行时调用 CRIU 工具,通过 ptrace 冻结容器进程树,注入寄生代码序列化内存与状态,最终打包成 tar.gz 归档

# 获取快照
sudo podman container checkpoint <container_id>

# 恢复快照
sudo podman container restore <container_id>
  1. Podman 卷管理

podman volume 是 Podman 管理的命名持久化存储对象,核心解决容器数据持久化与多容器共享问题;而 mkdir 创建的普通目录仅作为手动指定的挂载点(Bind Mount),缺乏生命周期管理与自动化能力

它是由 Podman 管理的命名持久化存储对象,本质是宿主机上的一个目录,但被 Podman 赋予了“身份”和“生命周期”

  • 创建:podman volume create mydata,Podman 自动在 /var/lib/containers/storage/volumes/mydata/_data(root 模式)或 ~/.local/share/containers/storage/volumes/mydata/_data(rootless 模式)下创建目录

  • 使用:podman run -v mydata:/app/data myimage,容器内 /app/data 的数据直接写入该目录

核心特性:
- 持久化:容器删除后数据仍在,新容器挂载同名卷即可复用 - 多容器共享:多个容器可同时挂载同一卷实现数据互通 - 独立管理:支持 ls、inspect、export、import、prune、rm 等完整生命周期管理 - 权限自动处理:自动处理 SELinux 标签和 UID/GID 映射,避免 Bind Mount 常见的权限拒绝问题

维度 podman volume(命名卷) mkdir + -v(Bind Mount)
管理方式 Podman 全生命周期管理(创建/删除/查看) 手动管理,Podman 不感知目录存在
存储位置 Podman 自动管理(/var/lib/containers/storage/volumes/... 用户任意指定路径(如 ~/data
权限处理 自动处理 SELinux 标签、UID/GID 映射 需手动 chown/chmod,易遇 Permission denied
跨主机迁移 配合 export/import 可打包迁移 需手动拷贝目录,路径可能不一致
驱动扩展 支持 NFS、云存储等第三方驱动 仅本地目录
适用场景 数据库、应用数据等容器专属持久化数据 配置文件、代码等宿主机已有文件

/var 是 Linux 中专门存放动态变化数据(variable data)的目录,而 /var/lib 专门用于存放应用程序运行时的持久化状态数据

# 创建命名卷
podman volume create mydata

# 查看所有卷
podman volume ls

# 查看卷详情
podman volume inspect mydata

# 删除卷
podman volume rm mydata

# 删除所有未使用的卷
podman volume prune

# 挂载命名卷
podman run -d -v mydata:/app/data nginx

# 只读挂载
podman run -d -v mydata:/app/data:ro nginx

# 挂载时指定驱动
podman run -d -v mydata:/app/data:z nginx
  1. SELinux 标签选项

SELinux 的标签选项(即安全上下文 Security Context)是 SELinux 实现强制访问控制(MAC)的核心机制,它为系统中的进程、文件、端口等资源分配唯一的安全标签,策略规则基于这些标签决定访问权限

对比项 :z(小写,共享标签) :Z(大写,私有标签)
标签类型 共享(shared) 私有(private/unshared)
SELinux 类型 container_file_t container_file_t
访问范围 所有容器均可访问该目录 仅当前容器可访问
安全性 较低,多容器共享权限 较高,独占隔离
适用场景 多容器协作共享数据 单容器独占使用(推荐)

# 私有标签(推荐)
podman run -v /data:/app:Z nginx

# 共享标签
podman run -v /shared:/app:z nginx