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 提供了对应命令。下面按典型操作顺序说明。
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 几乎一一对应,迁移成本很低,但有几处关键差异需要留意。
| 对比项 | Docker | Podman |
|---|---|---|
| 架构 | 客户端 + 守护进程 dockerd | 无守护进程,直接调用 runc/crun |
| root 权限 | 默认需 root 或 docker 组 | 支持 rootless,普通用户可运行 |
| 命令前缀 | docker | podman(多数子命令同名) |
| 编排 | docker-compose | podman-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