4. 使用Podman运行与管理容器

Podman 是 RHEL 8/9 默认提供的容器引擎,它遵循 OCI 标准,命令行与 Docker 高度兼容,但采用无守护进程(daemonless)架构,普通用户即可直接运行容器。本节围绕 podman run 的核心参数、容器生命周期管理命令,以及与 Docker 命令的差异展开,并完整实践一个 UBI httpd 容器的运行与访问验证。

一、podman run 的核心参数

podman run 是启动容器最常用的命令,其基本语法为:

podman run [选项] 镜像 [命令] [参数...]

下面四类参数在实际交付中最关键。

1. 端口映射 -p

容器内的服务默认只在容器网络命名空间内可见,必须通过 -p 主机端口:容器端口 暴露到宿主机。例如 -p 8080:80 表示把宿主机的 8080 端口转发到容器的 80 端口。若只写 -p 80,Podman 会随机分配一个宿主机端口,可用 podman port 查询。默认绑定 0.0.0.0,如需限制来源可写 -p 127.0.0.1:8080:80。

2. 卷挂载 -v

容器文件系统是临时的,删除容器后数据即丢失。使用 -v 宿主机路径:容器路径[:选项] 可将宿主机目录挂入容器。常用选项有 :Z(为 SELinux 重新打标签,RHEL 上挂载本地目录几乎必须加)、:ro(只读)。例如 -v /srv/web:/usr/local/apache2/htdocs:Z 把宿主机网页目录挂载到容器站点根目录。若使用命名卷,可写 -v webdata:/data,由 Podman 自动管理存储位置。

3. 环境变量 -e

通过 -e KEY=VALUE 向容器进程注入配置,例如 -e MYSQL_ROOT_PASSWORD=Redhat123。也可用 --env-file 文件 批量导入。注意环境变量会出现在 podman inspect 输出中,敏感信息应改用 secret 机制。

4. 资源限制

常用参数包括 --memory 512m 限制内存、--cpus 1.5 限制 CPU 核数、--pids-limit 100 限制进程数。这些限制依赖 cgroup v2,在 RHEL 9 上默认启用。合理设置可防止单个容器耗尽宿主机资源。

podman run 核心参数与容器运行关系 宿主机 RHEL 主机端口 8080 -p 8080:80 /srv/web 目录 -v ...:Z 环境变量 -e KEY=VALUE cgroup 资源限制 --memory / --cpus 容器 (UBI httpd) 容器端口 80 httpd 监听 /usr/local/apache2/htdocs 站点根目录 进程环境 读取注入变量 受限资源 内存/CPU 上限 curl 验证 http://主机:8080 返回网页内容 参数将宿主机资源与容器内部一一对应,形成可访问、可持久、可限制的运行实例

二、容器生命周期操作

容器从创建到销毁经历一系列状态,Podman 提供了对应命令。下面按典型操作顺序说明。

  • podman run:创建并启动容器,是最常用的入口。
  • podman ps -a:列出所有容器,-a 包含已停止的;不加则只看运行中。
  • podman stop 容器名:向容器主进程发送 SIGTERM,超时后发 SIGKILL,容器进入 Exited 状态。
  • podman start 容器名:重新启动已停止的容器,保留原有配置和数据。
  • podman exec -it 容器名 /bin/bash:在运行中的容器内执行命令,常用于排查问题。
  • podman logs 容器名:查看容器标准输出与标准错误,-f 可实时跟踪。
  • podman inspect 容器名:以 JSON 输出容器完整配置,包括 IP、挂载、环境变量、资源限制。
  • podman rm 容器名:删除已停止的容器,-f 可强制删除运行中的容器。

需要特别区分 stop 与 rm:stop 只是停止,容器仍存在,可再次 start;rm 则彻底删除,数据(未挂载的)随之丢失。生产环境建议先 stop 再 rm,避免误删。

三、与 Docker 命令的差异

Podman 命令与 Docker 几乎一一对应,迁移成本很低,但有几处关键差异需要留意。

对比项DockerPodman
架构客户端 + 守护进程 dockerd无守护进程,直接调用 runc/crun
root 权限默认需 root 或 docker 组支持 rootless,普通用户可运行
命令前缀dockerpodman(多数子命令同名)
编排docker-composepodman-compose 或 podman play kube
systemd 集成需额外配置podman generate systemd 原生支持

实际使用中,可以把 alias docker=podman 作为过渡,但要注意 docker build 对应 podman build,docker save/load 对应 podman save/load,镜像格式兼容 OCI,可互相导入。

四、实践:运行 UBI httpd 容器并验证访问

下面以 Red Hat 官方 UBI httpd 镜像为例,完整走一遍运行与验证流程。以下命令与输出为教学示例,实际结果以本机环境为准。

步骤 1:拉取镜像

podman pull registry.access.redhat.com/ubi9/httpd-24
podman images

步骤 2:准备网页目录

mkdir -p /srv/web
echo "Hello from UBI httpd on RHEL" > /srv/web/index.html
sudo chcon -Rt container_file_t /srv/web

在 RHEL 上,SELinux 默认启用,挂载本地目录必须打上 container_file_t 标签,否则容器内进程无权读取,页面会返回 403。使用 -v ...:Z 时 Podman 会自动处理,但手动 chcon 更直观。

步骤 3:运行容器

podman run -d --name web1 \
  -p 8080:8080 \
  -v /srv/web:/var/www/html:Z \
  -e APP_ENV=prod \
  --memory 256m --cpus 0.5 \
  registry.access.redhat.com/ubi9/httpd-24

UBI httpd-24 镜像默认监听 8080 端口,因此映射写 -p 8080:8080。若使用其他镜像监听 80,则改为 -p 8080:80。

步骤 4:验证运行状态

podman ps
podman logs web1
podman inspect web1 | grep -i -A3 Memory

podman ps 应显示 web1 处于 Up 状态;podman logs 可看到 httpd 启动日志;podman inspect 中 Memory 字段应显示 268435456(即 256MiB)。

步骤 5:访问验证

curl http://localhost:8080
# 预期输出:Hello from UBI httpd on RHEL

若返回 403,检查 SELinux 标签与目录权限;若连接被拒绝,检查端口映射与 httpd 是否监听 8080;若返回默认页面而非自定义内容,说明挂载路径与镜像站点根目录不一致,可用 podman exec web1 ls /var/www/html 确认。

步骤 6:进入容器排查

podman exec -it web1 /bin/bash
# 容器内执行
curl http://localhost:8080
exit

在容器内访问成功而宿主机失败,问题通常出在端口映射或防火墙;两者都失败则问题在 httpd 配置或挂载内容。

步骤 7:清理

podman stop web1
podman rm web1
建议为容器命名(--name),便于后续 start/stop/exec/logs 操作;避免使用容器 ID 前缀,容易混淆。
使用 -v 挂载宿主机目录时,务必确认 SELinux 标签正确,否则容器内进程会因权限被拒绝而无法读取文件,表现为 403 或启动失败。