十二.运行容器
3.管理容器存储和网络资源
3.1管理容器资源
容器默认是临时、无状态的(容器删除后,内部数据和配置会丢失)。但像数据库、文件存储这类 "需要长期运行且数据不能丢" 的服务,必须添加持久存储 (确保数据永久保存)和DNS 解析(确保容器能在网络中正确寻址):
3.2持久存储
3.2.1容器持久存储
默认容器存储为临时存储,容器删除后数据丢失,需挂载主机目录实现持久化。
通过在容器上创建挂载的目录,映射到容器主机上创建持久存储。将容器内的存储目录与 主机或外部存储系统关联,即使容器重启 / 删除,数据也能保留(例如数据库的/var/lib/mysql目录挂载到主机的持久化路径)。
操作:(手动配置GID/UID)
前提:已经创建并运行该容器
适用于自定义镜像或非标准用户权限的场景
(1)主机上创建存储目录
mkdir -p $HOME/目录名字
要求权限至少为700(保证主机目录所有者需与容器内进程的 UID/GID 一致)
如:

(2)配置目录权限
podman unshare chown UID:GID 目录
需要与容器内进程UID/GID匹配
如:
先从容器中获取需要的UID/GID
podman exec -it 容器名 grep 容器内服务 /etc/passwd

再配置主机目录中的UID/GID
podman unshare chown 27:27 /home/student/databases/

验证:

(3)停止并删除容器
podman stop 容器
podman rm 容器
(4)挂载目录并启动容器(绝对路径)
podman run -v 主机目录:容器目录 镜像名
如:
podman run -d --name 容器名 \
-v 主机目录:容器目录 \
镜像地址

注:
已创建 的容器无法直接补充挂载 ,需要删除后 重新按需求创建,建议删除前备份数据。
3.2.2容器存储的SELinux上下文
当用podman run -v将主机目录挂载到容器作为持久存储 时,若主机目录的 SELinux 上下文不是container_file_t ,容器内进程 会因权限被拒而无法访问该目录,导致数据持久化失败(比如数据库容器无法写入数据)。
必须设置目录container_file_t SELinux Context,才能作为持久存储挂载到容器。
方法:
:Z选项自动配置上下文;
在podman run -v挂载目录时,添加:Z选项,Podman 会自动将主机目录的 SELinux 上下文设置为container_file_t,让容器进程有权限访问。
即:(自动挂载)
podman run -v 主机目录:容器目录 镜像名
如:
podman run -d --name 容器名 \
-v 主机目录:容器目录****:Z****\
registry.lab.example.com/rhel8/镜像名

3.2.3目录挂载(bind mount 绑定挂载)
对于仅需单个容器 、无需横向扩展 的简单场景(如个人测试、小型工具服务),可直接通过"目录挂载"实现持久存储:
操作:
podman run -v 主机路径:容器路径[:权限选项] 镜像名称
|--------------|--------------------------------------------|---------------|--------------------------------------------------------------|
| 参数部分 | 含义 | 可选/必选 | 格式要求与示例 |
| 主机路径 | 主机上要挂载的目录或文件(必须是绝对路径 ,不能用相对路径) | 必选 | 目录:/home/user/data、$HOME/nginx/html; 文件:/etc/hosts |
| 容器路径 | 容器内要关联的目录或文件(必须是绝对路径 ,容器内不存在会自动创建) | 必选 | 目录:/app/data、/usr/share/nginx/html; 文件:/etc/nginx/nginx.conf |
| 权限选项 | 限制容器对挂载目录的操作权限(默认rw可读写) | 可选 | rw(默认,可读写) ro(只读,容器无法修改主机文件) |
如:
podman run -v****$HOME/test**** :/app/data nginx
主机 $HOME/test 目录挂载到容器 /app/data,双向可读写
3.3容器中的DNS解析
默认情况:Podman 容器默认网络不支持 DNS 解析,容器间无法通过名称通信。
自RHEL9起,Podman v4.0 默认使用 Netavark 网络后端。
podman info --format {{.Host.NetworkBackend}}

操作:
(1)创建支持DNS的网络
podman network create \
--gateway 网关IP --subnet 子网 网络名
如:
创建具有10.89.1.0/24子网和10.89.1.1网关的frontend网络
podman network create \
--gateway 10.89.1.1 --subnet 10.89.1.0/24 frontend

(2)启动容器时加入该网络
podman run --network 网络名 镜像名

(3)容器内安装网络根据测试,并通过"ping 容器名"验证DNS解析
podman exec -it 容器名字 \
dnf install iputils iproute
如:
在容器db_client中,启动容器db_01中的数据库
podman exec -it db_client mysql -u dev1 -p -h db_01

解释:
(1) podman exec -it db_client:
在运行中的db_client容器内,执行交互式命令(-it 保证输入输出的交互性,让用户能输入密码、执行 SQL)。
(2) mysql -u dev1 -p -h db_01:
用于启动 MariaDB 客户端工具。
-u dev1:
指定连接数据库的用户为dev1(该用户是在db_01容器启动时,通过环境变量MYSQL_USER=dev1初始化的);
-p:
提示输入用户密码(对应MYSQL_PASSWORD=devpass,需手动输入);
-h db_01:
指定连接的数据库主机为db_01容器(依赖容器网络的 DNS 解析能力------ 同一网络内的容器可通过名称直接解析为 IP,无需手动配置)。
3.4多网络连接到单容器
多网络连接的核心是让单个容器接入多个独立网络,实现不同流量隔离(如业务流量、管理流量)、多服务网段通信等需求。
本质是通过为容器分配多个网络接口 (每个网络对应一个 IP),灵活适配复杂网络场景。
操作:
(1)创建多个网络
podman network create 网络1 \
podman network create 网络2
如:

(2)运行中容器连接新网络
podman network connect 网络名 容器名

(3)验证
查看容器的多网络IP配置(Networks信息)
podman inspect 容器名

容器已经添加两个网络,backend和frontend
测试两个容器间通信:
podman exec -it 容器A ping -c4 容器B
如:
podman exec -it db_client ping -c4 db_01

注:
使用Ping命令测试前,需要安装iputils软件包:
podman exec -it 容器A dnf install iputils
3.5分配端口映射到容器
端口映射是 Podman中打通容器网络隔离 的核心功能,核心是将****"主机的端口**** " 与"容器内服务的端口 "建立绑定 ,实现外部客户端 (主机、局域网设备、公网)对容器内服务的访问。适用于仅需单个容器、无需复杂网络规划的简单场景,无需额外网络组件。
格式:
podman run -p 主机IP:主机端口:容器端口/协议类型 镜像名称
|--------------|------------------------------------------------|---------------|------------------------------------------------------------------|
| 参数部分 | 含义 | 可选/必选 | 格式要求与示例 |
| 主机IP | 指定主机的网卡 IP(限制仅该 IP 对外提供服务),默认 0.0.0.0(所有网卡可访问) | 可选 | 局域网 IP:192.168.1.100(仅局域网设备访问);公网 IP:203.0.113.5(公网可访问) |
| 主机端口 | 主机上对外开放的端口(需未被其他程序占用),范围 1-65535 | 必选 | 8080、9000(推荐用 1024 以上端口,避免与系统预留端口冲突) |
| 容器端口 | 容器内服务实际监听的端口(需与容器内应用配置一致) | 必选 | 80(Nginx 默认)、5000(Python Flask 默认)、3306(MySQL 默认)、6379(Redis 默认) |
| 协议类型 | 指定网络协议(TCP/UDP),默认 TCP(大部分服务用 TCP) | 可选 | /tcp(默认,可省略)、/udp(如 DNS、视频流服务) |
如:
podman run -p 8080:80 nginx
主机 8080 端口映射到容器 80 端口,所有网卡(本地、局域网、公网)可访问
操作:
(1)配置端口映射
podman run -p 主机IP:主机端口:容器端口

(2)查看端口映射关系
podman port 容器名字

(3)开放主机防火墙端口
firewall-cmd --add-port=主机端口/tcp --permanent
firewall-cmd --reload

注:
端口映射 是主机和容器的端口绑定,启动后无法动态添加/修改。需要删除旧容器 ,然后按需创建。
3.6容器的环境变量
3.6.1定义
容器的环境变量是在容器启动时注入到容器内部的 "键值对",容器内的应用可通过读取这些变量,动态调整自身行为(如配置数据库密码、服务端口、日志级别等)。
实现了"配置与代码分离",让容器更灵活、可复用(同一镜像可通过不同环境变量适配不同场景)。
3.6.2作用
容器化应用的配置需求通常是动态且场景化的(如开发 / 测试 / 生产环境的数据库地址不同),环境变量解决了以下痛点:
(1)配置动态化
无需修改应用代码或配置文件,仅通过启动参数 即可调整应用行为;
(2)敏感信息隔离:
数据库密码、API 密钥等敏感信息不硬编码在代码中,降低泄露风险;
(3)镜像复用性:
同一镜像 可通过不同环境变量 ,在开发、测试、生产等场景中复用。
3.6.3关键操作
(1)排查因为缺少环境变量导致的失败原因:
podman container logs 容器名字
如:
podman container logs db_01

必须配置至少一组环境变量 来初始化数据库,否则容器无法正常启动
(2)传递环境变量,多个变量使用多个-e选项:
podman run -e 变量名=值
如:

(3)查看镜像所需要的环境变量说明:
skopeo inspect 镜像地址

3.7 总结------管理容器存储和网络一般流程
现有:
网络:frontend
子网:10.89.1.0/24
网关:10.89.1.1
容器:db_client、db_01
3.7.1创建网络并连接容器
(1)创建网络
podman network create \
--gateway 网关 --subnet 子网 \
网络名字

创建时指定子网和网关,避免与现有网络冲突,同时确保网络支持 DNS 解析。
(2)创建容器
podman run -d --name 容器名 \
--network 网络名
镜像地址

或者使用已经创建好的容器连接到网络:
podman network connect 网络名 容器名
注:
已运行容器关联网络后,需重启容器使配置生效(podman restart 容器名)。
(3)验证:

3.7.2持久化挂载
3.7.2.1(直接挂载)
适用于官方标准化镜像,如 MariaDB、Nginx 官方镜像;
需要挂载的容器名字:db_client
主机:/etc/yum.repos.d
容器路径:/etc/yum.repos.d
(1)删除已经创建的容器
podman rm 容器名

(2)重新创建持久挂载的容器
podman run -d --name db_client \
--network 网络名字 \
-v 主机文件:容器文件 \
镜像地址
如:

(3)验证:

3.7.2.2(手动挂载)
(1)主机创建存储目录(权限≥700 )

(2)获取容器内进程的 UID/GID(以 MySQL 为例)

(3)配置主机目录权限

(4)停止并删除旧容器

(5)重建容器并挂载

(6)验证挂载是否有效
3.7.3故障排除
(1)查看容器日志确定原因
podman container logs 容器名
如:

启动 MariaDB 容器时,必须配置至少一组环境变量 来完成数据库初始化,否则容器无法正常启动。
(2)删除旧容器
podman rm db_01

(3)使用环境变量重新创建容器
podman run -d --name 容器名字 \
--network frontend \
-e MYSQL_USER=dev1 \
-e MYSQL_PASSWORD=123456 \
通过-e选项设置上述找出的需要配置的环境变量

如:

3.7.4端口映射
主机端口:13306
容器端口:3306
主机的防火墙允许13306的端口流量
(1)删除旧容器

(2)创建带有端口映射的容器
podman run -d --name db_01 \
--network 网络名字 \
-e 环境变量配置 \
-v 主机文件:容器路径:Z \ #持久化挂载
-p 13306:3306 \
镜像地址

(3)验证
podman ps -a

(4)开放防火墙
firewall-cmd --add-port=主机端口/tcp --permanent
firewall-cmd --reload
如:

通过本篇的实操,解决容器 "数据丢失" 和 "网络隔离" 的核心问题,容器具备了稳定运行的基础条件。但在生产环境中,还需实现容器的 "服务化运维"------ 如主机开机自启、故障自动恢复、日志集中管理等。'下一篇将聚焦如何通过 systemd 将容器封装为系统服务,实现容器的自动化管理,进一步提升运维效率,为规模化部署保驾护航。
