目录

1. 培训目标与容器管理基础

培训目标概述

容器资源管理策略

2. 环境变量配置:容器自定义的关键

问题发现与诊断

镜像信息获取与解析

MariaDB环境变量详解

正确配置环境变量

3. 容器持久存储配置

存储需求背景

文件系统权限配置

Rootless容器的UID/GID映射

创建持久存储目录

挂载持久存储

4. SELinux上下文配置

权限错误分析

SELinux解决方案

5. 容器端口映射配置

端口映射原理

验证端口映射

防火墙配置

Rootless容器端口限制

6. 容器DNS配置与网络连接

网络后端检测

创建支持DNS的网络

验证网络配置

容器连接到自定义网络

安装网络测试工具

DNS解析测试

IP地址验证

7. 多网络连接配置

创建第二个网络

查看所有网络

动态连接额外网络

验证多网络配置

多网络连通性测试

总结


1. 培训目标与容器管理基础

培训目标概述

通过从容器主机共享存储为容器数据提供持久化存储,并配置容器网络环境。这对于运行数据库等需要数据持久化的服务至关重要。

容器资源管理策略

容器可以运行简单的临时进程,也可以配置为持续运行服务(如数据库服务器)。对于长期运行的服务,需要额外配置:

  • 持久存储:确保数据在容器重启或删除后不丢失

  • 网络访问:允许外部客户端访问容器服务


2. 环境变量配置:容器自定义的关键

问题发现与诊断

首次尝试运行MariaDB容器失败:

podman run -d registry.lab.example.com/rhe18/mariadb-105 --name db01

使用 podman container logs db01 检查日志,发现容器需要特定的环境变量才能正常启动:

日志分析结果:

You must either specify the following environment variables:
    MYSQL_USER (regex: '^[a-zA-Z0-9_]+$')
    MYSQL_PASSWORD (regex: '^[a-zA-Z0-9_\-!@#$%^&*()\-=<>,.?;:]+$')
    MYSQL_DATABASE (regex: '^[a-zA-Z0-9_]+$')
Or the following environment variable:
    MYSQL_ROOT_PASSWORD (regex: '^[a-zA-Z0-9_\-!@#$%^&*()\-=<>,.?;:]+$')
Or both.

问题根源:MariaDB容器需要数据库配置信息,但未提供必需的环境变量。

镜像信息获取与解析

使用 skopeo inspect 命令查看镜像元数据:

skopeo inspect docker://registry.lab.example.com/rhel8/mariadb-105

关键发现

  • usage 字段提供了运行示例

  • 镜像文档显示了可用的环境变量

MariaDB环境变量详解

变量名描述正则验证规则
MYSQL_USER要创建的MySQL帐户用户名^[a-zA-Z0-9_]+$
MYSQL_PASSWORD用户帐户密码^[a-zA-Z0-9_\-!@#$%^&*()\-=<>,.?;:]+$
MYSQL_DATABASE数据库名称^[a-zA-Z0-9_]+$
MYSQL_ROOT_PASSWORDroot用户密码(可选)^[a-zA-Z0-9_\-!@#$%^&*()\-=<>,.?;:]+$

正确配置环境变量

使用 -e 选项传递环境变量:

podman run -d --name db01 \
-e MYSQL_USER=student \
-e MYSQL_PASSWORD=student \
-e MYSQL_DATABASE=dev_data \
-e MYSQL_ROOT_PASSWORD=redhat \
registry.lab.example.com/rhe18/mariadb-105

验证容器状态

podman ps

输出结果解析

CONTAINER ID IMAGE    COMMAND               CREATED STATUS PORTS NAMES
4b8f01be7fd6 registry.lab.example.com/rhe18/mariadb-105:latest run-mysqld 6 seconds ago Up 6 seconds ago db01
  • STATUS: Up 6 seconds:容器正常运行

  • 相比之前的 Exited (1) 状态,说明环境变量配置成功


3. 容器持久存储配置

存储需求背景

默认情况下,容器使用基于镜像的存储层,所有新数据在容器删除后都会丢失。对于数据库等需要数据持久化的应用,必须配置持久存储。

文件系统权限配置

MariaDB容器中,mysql用户必须拥有/var/lib/mysql目录的权限。

查看容器内mysql用户信息

podman exec -it db01 grep mysql /etc/passwd

输出mysql:x:27:27:MySQL Server:/var/lib/mysql:/sbin/nologin

关键信息:mysql用户的UID和GID都是27

Rootless容器的UID/GID映射

在Rootless容器中,用户命名空间内的UID/GID与主机上的UID/GID存在映射关系:

podman unshare cat /proc/self/uid_map

输出分析

text

0    1000    1
1    100000    65536
  • 容器内UID 0 → 主机UID 1000

  • 容器内UID 1 → 主机UID 100000

  • 容器内UID 27 → 主机UID 100026

创建持久存储目录

mkdir /home/user/db_data
podman unshare chown 27:27 /home/user/db_data

验证目录所有权

ls -l /home/user/

输出drwxrwxr-x. 3 100026 100026 18 May 5 14:37 db_data

结果说明:目录所有者为UID 100026,对应容器内的UID 27

挂载持久存储

使用-v选项挂载目录:

podman run -d --name db01 \
-e MYSQL_USER=student \
-e MYSQL_PASSWORD=student \
-e MYSQL_DATABASE=dev_data \
-e MYSQL_ROOT_PASSWORD=redhat \
-v /home/user/db_data:/var/lib/mysql \
registry.lab.example.com/rhel8/mariadb-105

4. SELinux上下文配置

权限错误分析

容器日志显示权限错误:

podman container logs db01

错误信息

mkdir: cannot create directory '/var/lib/mysql/db_data': Permission denied
Fatal error Can't create database directory '/var/lib/mysql/db_data'

问题根源:SELinux安全上下文不正确,阻止容器访问主机目录。

SELinux解决方案

容器存储需要container_file_t SELinux上下文类型。使用Z选项自动设置正确上下文:

podman run -d --name db01 \
-e MYSQL_USER=student \
-e MYSQL_PASSWORD=student \
-e MYSQL_DATABASE=dev_data \
-e MYSQL_ROOT_PASSWORD=redhat \
-v /home/user/db_data:/var/lib/mysql:Z \
registry.lab.example.com/rhel8/mariadb-105

验证SELinux上下文

ls -z /home/user/

输出system_u:object_r:container_file_t:s0:c81,c1009 db_data

结果说明:目录已正确标记为container_file_t类型,容器可以正常访问。


5. 容器端口映射配置

端口映射原理

将容器主机上的网络端口映射到容器内部端口,实现外部客户端访问容器服务。

配置端口映射

podman run -d --name db01 \
-e MYSQL_USER=student \
-e MYSQL_PASSWORD=student \
-e MYSQL_DATABASE=dev_data \
-e MYSQL_ROOT_PASSWORD=redhat \
-v /home/user/db_data:/var/lib/mysql:Z \
-p 13306:3306 \
registry.lab.example.com/rhe18/mariadb-105

映射说明

  • 主机端口:13306

  • 容器端口:3306

  • 发送到主机13306端口的流量将被转发到容器的3306端口

验证端口映射

podman port -a

输出1c22fd905120 3306/tcp -> 0.0.0.0:13306

podman port db01

输出3306/tcp -> 0.0.0.0:13306

结果分析:成功建立从主机13306端口到容器3306端口的映射。

防火墙配置

允许外部访问13306端口:

firewall-cmd --add-port=13306/tcp --permanent
firewall-cmd --reload

Rootless容器端口限制

重要限制

  • Rootless容器无法绑定1024以下的特权端口

  • 可以使用podman run -p 8080:80将高端口映射到容器特权端口

  • 需要特权端口时,必须以root用户运行Podman


6. 容器DNS配置与网络连接

网络后端检测

Podman支持多种网络后端:

podman info --format {{.Host.NetworkBackend}}

输出netavark

网络后端类型

  • Netavark:RHEL 9+默认后端

  • CNI:传统后端

创建支持DNS的网络

默认Podman网络不支持DNS解析,需要创建自定义网络:

podman network create --gateway 10.87.0.1 --subnet 10.87.0.0/16 db_net

网络配置说明

  • 网络名称:db_net

  • 网关:10.87.0.1

  • 子网:10.87.0.0/16

验证网络配置

podman network inspect db_net

输出分析:显示网络详细信息,确认网关、子网和DNS设置正确。

容器连接到自定义网络

创建连接到db_net网络的容器:

数据库容器

podman run -d --name db01 \
-e MYSQL_USER=student \
-e MYSQL_PASSWORD=student \
-e MYSQL_DATABASE=dev_data \
-e MYSQL_ROOT_PASSWORD=redhat \
-v /home/user/db_data:/var/lib/mysql:Z \
-p 13306:3306 \
--network db_net \
registry.lab.example.com/rhe18/mariadb-105

客户端容器

podman run -d --name client01 \
--network db_net \
registry.lab.example.com/ubi8/ubi:latest \
sleep infinity

安装网络测试工具

容器镜像通常只包含最小软件包,需要安装网络工具:

podman exec -it db01 dnf install -y iputils iproute
podman exec -it client01 dnf install -y iputils iproute

DNS解析测试

测试容器间通过主机名通信:

podman exec -it db01 ping -c3 client01

输出分析

PING client01.dns.podman (10.87.0.4) 56(84) bytes of data.
64 bytes from 10.87.0.4 (10.87.0.4): icmp_seq=1 ttl=64 time=0.049 ms
-- client01.dns.podman ping statistics --
3 packets transmitted, 3 received, 0% packet loss, time 2007ms
podman exec -it client01 ping -c3 db01

输出分析

PING db01.dns.podman (10.87.0.3) 56(84) bytes of data.
64 bytes from 10.87.0.3 (10.87.0.3): icmp_seq=1 ttl=64 time=0.021 ms
-- db01.dns.podman ping statistics --
3 packets transmitted, 3 received, 0% packet loss, time 2047ms

测试结果

  • 成功通过容器名进行DNS解析

  • 网络延迟正常,无丢包

  • 容器间通信正常

IP地址验证

podman exec -it db01 ip a | grep 10.8

输出inet 10.87.0.3/16 brd 10.87.255.255 scope global eth0

podman exec -it client01 ip a | grep 10.8

输出inet 10.87.0.4/16 brd 10.87.255.255 scope global eth0

IP分配确认

  • db01: 10.87.0.3

  • client01: 10.87.0.4


7. 多网络连接配置

创建第二个网络

podman network create backend

查看所有网络

podman network ls

输出

NETWORK ID    NAME    DRIVER
a7fea510a6d1   backend    bridge
fe680efc5276   db_net    bridge
2f259bab93aa   podman    bridge

动态连接额外网络

运行时将backend网络连接到现有容器:

podman network connect backend db01
podman network connect backend client01

验证多网络配置

podman inspect db01

网络配置输出

"backend": {
    "EndpointID": "",
    "Gateway": "10.89.1.1",
    "IPAddress": "10.89.1.4",
},
"db_net": {
    "EndpointID": "",
    "Gateway": "10.87.0.1",
    "IPAddress": "10.87.0.3",
}
podman inspect client01

网络配置输出

"backend": {
    "EndpointID": "",
    "Gateway": "10.89.1.1",
    "IPAddress": "10.89.1.5",
},
"db_net": {
    "EndpointID": "",
    "Gateway": "10.87.0.1",
    "IPAddress": "10.87.0.4",
}

多网络IP分配

  • db01: db_net(10.87.0.3), backend(10.89.1.4)

  • client01: db_net(10.87.0.4), backend(10.89.1.5)

多网络连通性测试

podman exec -it client01 ping -c3 10.89.1.4 | grep 'packet loss'

输出3 packets transmitted, 3 received, 0% packet loss, time 2052ms

podman exec -it client01 ping -c3 10.87.0.3 | grep 'packet loss'

输出3 packets transmitted, 3 received, 0% packet loss, time 2054ms

测试结论:client01容器可以通过两个网络与db01容器通信。


总结

通过完整的配置过程,我们成功实现了:

  1. 环境变量配置:正确传递数据库配置参数

  2. 持久存储:配置主机目录映射,确保数据持久化

  3. SELinux安全:正确设置安全上下文,确保容器访问权限

  4. 网络端口映射:实现外部客户端访问容器服务

  5. DNS解析:创建自定义网络,支持容器间通过主机名通信

  6. 多网络连接:实现网络流量分离和管理

更多推荐