在 RHEL 8 上使用容器
在 RHEL 8 系统中,我们可以借助 Podman、Skopeo 和 Buildah 等工具来创建和管理容器。下面将详细介绍如何在 RHEL 8 上进行容器的相关操作。
1. 安装容器工具
在开始使用容器之前,需要先安装所有的容器工具,可使用以下命令:
# dnf module install container-tools
2. 登录 Red Hat 容器注册表
若要从 Red Hat 容器注册表中拉取镜像到本地系统,需先使用现有的 Red Hat 凭证登录注册表,使用
podman
工具的命令如下:
# podman login registry.redhat.io
Username: yourusername
Password: yourpassword
当看到
Login Succeeded!
时,表示登录成功。
3. 拉取容器镜像
这里以从注册表中拉取 RHEL 8 通用基础镜像(UBI)为例。在拉取镜像前,可使用
skopeo
工具获取镜像仓库的信息,示例命令如下:
# skopeo inspect docker://registry.redhat.io/ubi8/ubi-init
输出信息如下:
{
"Name": "registry.redhat.io/ubi8/ubi-init",
"Digest": "sha256:143375cad82a2e5578b19559e7c176558bb2a857d66b541706274edc380161c3",
"RepoTags": [
"8.1",
"8.0",
"8.0-15",
"8.1-14",
"8.0-22",
"8.0-20",
"8.0-7",
"latest"
],
"Created": "2019-10-29T20:21:43.695804Z",
"DockerVersion": "1.13.1",
"Labels": {
"architecture": "x86_64",
"authoritative-source-url": "registry.access.redhat.com",
"build-date": "2019-10-29T20:21:10.175846",
"com.redhat.build-host": "cpt-1004.osbs.prod.upshift.rdu2.redhat.com",
"com.redhat.component": "ubi8-init-container",
"com.redhat.license_terms": "https://www.redhat.com/en/about/red-hat-end-user-license-agreements#UBI",
"description": "The Universal Base Image Init is designed is designed to run an init system as PID 1 for running multi-services inside a container. This base image is freely redistributable, but Red Hat only supports Red Hat technologies through subscriptions for Red Hat products. This image is maintained by Red Hat and updated regularly.",
"distribution-scope": "public",
"io.k8s.description": "The Universal Base Image Init is designed is designed to run an init system as PID 1 for running multi-services inside a container. This base image is freely redistributable, but Red Hat only supports Red Hat technologies through subscriptions for Red Hat products. This image is maintained by Red Hat and updated regularly.",
"io.k8s.display-name": "Red Hat Universal Base Image 8 Init"
}
}
ubi-init
镜像为构建最小操作系统容器的 RHEL 8 基础镜像,确认该镜像无误后,使用以下
podman
命令将其拉取到本地系统:
# podman pull docker://registry.redhat.io/ubi8/ubi-init
拉取过程中会有如下输出:
Trying to pull docker://registry.redhat.io/ubi8/ubi-init...Getting image source signatures
Copying blob 340ff6d7f58c done
Copying blob 0e8ea260d026 done
Copying blob c3bd58a6898a done
Copying config a4933472b1 done
Writing manifest to image destination
Storing signatures
a4933472b168b6bd21bc4922dc1e72bb2805d41743799f5a823cdeca9a9a6613
可通过
podman
列出所有本地镜像来验证镜像是否已存储:
# podman images
输出示例:
| REPOSITORY | TAG | IMAGE ID | CREATED | SIZE |
| — | — | — | — | — |
| registry.redhat.io/ubi8/ubi-init | latest | a4933472b168 | 6 weeks ago | 254 MB |
若要获取本地镜像的详细信息,可运行
podman inspect
命令:
# podman inspect registry.redhat.io/ubi8/ubi-init
该命令输出的信息应与前面使用
skopeo
命令获取的远程镜像信息相同。
4. 在容器中运行镜像
从注册表拉取的镜像为可直接在容器中运行的完整镜像,无需修改。使用
podman run
命令运行镜像,这里使用
–rm
选项,表示在容器中运行镜像、执行一个命令后让容器退出。以下示例使用
cat
工具输出容器根文件系统中
/etc/passwd
文件的内容:
# podman run --rm registry.redhat.io/ubi8/ubi-init cat /etc/passwd
输出内容如下:
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:65534:65534:Kernel Overflow User:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
systemd-coredump:x:999:997:systemd Core Dumper:/:/sbin/nologin
systemd-resolve:x:193:193:systemd Resolver:/:/sbin/nologin
将容器内
/etc/passwd
文件的内容与主机系统上的该文件内容进行比较,可发现容器内缺少主机上的额外用户,这证实了
cat
命令是在容器环境中执行的。而且容器启动、执行命令并退出仅需几秒,相比启动完整操作系统、执行任务并关闭虚拟机所需的时间,能明显感受到容器的速度和效率。
若要启动容器并保持其运行,同时访问其 shell,可使用以下命令:
# podman run --name=mycontainer -it registry.redhat.io/ubi8/ubi-init /bin/bash
执行后会进入容器的 shell:
[root@dbed2be11730 /]#
这里使用了额外的命令行选项为容器指定名称
mycontainer
,虽为可选操作,但这样能更方便地识别和引用容器,替代使用自动生成的容器 ID。
容器运行时,可在另一个终端窗口运行
podman
查看系统中所有容器的状态:
# podman ps -a
输出示例:
| CONTAINER ID | IMAGE | COMMAND | CREATED | STATUS | PORTS | NAMES |
| — | — | — | — | — | — | — |
| dbed2be11730 | registry.redhat.io/ubi8/ubi:latest | /bin/bash | 5 minutes ago | Up 2 minutes ago | | mycontainer |
若要从主机在运行的容器中执行命令,可使用
podman exec
命令,指定运行容器的名称和要执行的命令。例如,在名为
mycontainer
的容器中启动第二个
bash
会话:
# podman exec -it mycontainer /bin/bash
同样,也可使用
podman ps -a
命令列出的容器 ID 达到相同效果:
# podman exec -it dbed2be11730 /bin/bash
另外,
podman attach
命令也可连接到运行的容器并访问其 shell 提示符:
# podman attach mycontainer
容器启动并运行后,可像操作其他 RHEL 8 系统一样进行额外的配置更改和安装软件包。
5. 管理容器
容器启动后会持续运行,直到通过
podman
停止或容器运行时启动的命令退出。例如,在主机上运行以下命令可使容器退出:
# podman stop mycontainer
或者,在容器的最后一个
bash
shell 中按下
Ctrl-D
组合键,也会使 shell 和容器退出。容器退出后,其状态会相应改变,可通过以下命令查看:
# podman ps -a
输出示例:
| CONTAINER ID | IMAGE | COMMAND | CREATED | STATUS | PORTS | NAMES |
| — | — | — | — | — | — | — |
| dbed2be11730 | registry.redhat.io/ubi8/ubi:latest | /bin/bash | 9 minutes ago | Exited (0) 14 seconds ago | | mycontainer |
虽然容器不再运行,但它仍然存在,并且包含对配置和文件系统所做的所有更改。若安装了软件包、进行了配置更改或添加了文件,这些更改将保留在
mycontainer
中。可使用以下命令重启容器进行验证:
# podman start mycontainer
容器启动后,可再次使用
podman exec
命令在容器内执行命令,例如再次访问 shell 提示符:
# podman exec -it mycontainer /bin/bash
运行中的容器还可使用
podman pause
和
podman unpause
命令进行暂停和恢复操作:
# podman pause mycontainer
# podman unpause mycontainer
6. 将容器保存为镜像
当容器的客户系统配置满足需求后,可能需要创建并运行多个该类型的容器。为此,需将容器保存为镜像到本地存储,以便作为额外容器实例的基础。可使用
podman commit
命令结合容器的名称或 ID 以及镜像的存储名称来实现,示例如下:
# podman commit mycontainer myrhel_image
镜像保存后,可检查其是否出现在本地仓库的镜像列表中:
# podman images
输出示例:
| REPOSITORY | TAG | IMAGE ID | CREATED | SIZE |
| — | — | — | — | — |
| localhost/myrhel_image | latest | 4d207635db6c | 9 seconds ago | 239 MB |
| registry.redhat.io/ubi8/ubi-init | latest | a4933472b168 | 6 weeks ago | 254 MB |
保存的镜像可用于创建与原始容器相同的额外容器:
# podman run --name=mycontainer2 -it localhost/myrhel_image /bin/bash
7. 从本地存储中删除镜像
若不再需要某个镜像,可使用
podman rmi
命令将其从本地存储中删除,需参考
podman images
命令输出的镜像名称或 ID。例如,删除上一节创建的名为
myrhel_image
的镜像:
# podman rmi localhost/myrhel_image
注意,在删除镜像之前,必须先删除基于该镜像的所有容器。
8. 删除容器
即使容器已退出或停止,它仍然存在且可随时重启。若不再需要某个容器,可在停止容器后使用
podman rm
命令将其删除,示例如下:
# podman rm mycontainer2
9. 使用 Buildah 构建容器
Buildah 可基于现有容器、镜像或完全从头开始构建新容器,还能挂载容器的文件系统,以便从主机访问和修改。
例如,使用以下
buildah
命令从 RHEL 8 基础镜像构建容器(若镜像尚未从注册表拉取,
buildah
会在创建容器前下载该镜像):
# buildah from registry.redhat.io/ubi8/ubi-init
运行该命令后,会得到一个名为
ubi-init-working-container
的可运行容器,可使用以下命令验证:
# buildah run ubi-init-working-container cat /etc/passwd
10. 从头开始构建容器
从头构建容器实际上是创建一个空容器,创建完成后可安装软件包以满足容器的需求。这种方法在创建仅需安装最少软件包的容器时很有用。
从头构建的第一步是运行以下命令构建空容器:
# buildah from scratch
构建完成后,会创建一个名为
working-container
的新容器,可使用以下命令查看:
# buildah containers
输出示例:
| CONTAINER ID | BUILDER | IMAGE ID | IMAGE NAME | CONTAINER NAME |
| — | — | — | — | — |
| dbed2be11730 | * | cb642e6a9917 | registry.redhat.io/ubi8/ubi:latest | dbed2be1173000c099ff29c96eae59aed297b82412b240a8ed29ecec4d39a8ba |
| 17df816ea0bb | * | a4933472b168 | registry.redhat.io/ubi8/ubi-init:latest | ubi-init-working-container |
| 65b424a31039 | * | scratch | | working-container |
空容器准备好安装软件包,但由于此时容器内甚至没有
bash
或
dnf
工具,无法在容器内执行安装操作。因此,需要将容器文件系统挂载到主机系统,并使用
dnf
命令在挂载的容器文件系统上进行软件包安装。首先,使用以下命令挂载容器的文件系统:
# buildah mount working-container
若文件系统挂载成功,
buildah
会输出容器文件系统的挂载点。挂载成功后,可使用
dnf
命令结合
–installroot
选项将软件包安装到容器中,示例如下(
<container_fs_mount>
为
buildah mount
命令之前输出的挂载路径):
# dnf install --releasever=8.1 --installroot <container_fs_mount> bash coreutils dnf
--releasever
选项用于告知
dnf
要在容器内安装 RHEL 8.1 的软件包。
安装完成后,使用以下命令卸载临时文件系统:
# buildah umount working-container
dnf
完成软件包安装后,可运行容器并访问
bash
命令提示符:
# buildah run working-container bash
输出示例:
bash-4.4#
11. 容器桥接网络
容器网络使用容器网络接口(CNI)桥接网络栈实现。以下命令展示了运行容器的主机系统上的典型网络配置:
# ip a
输出示例:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 08:00:27:20:dc:2f brd ff:ff:ff:ff:ff:ff
inet 192.168.0.33/24 brd 192.168.0.255 scope global dynamic noprefixroute enp0s3
valid_lft 3453sec preferred_lft 3453sec
inet6 2606:a000:4307:f000:aa6:6da1:f8a9:5f95/64 scope global dynamic noprefixroute
valid_lft 3599sec preferred_lft 3599sec
inet6 fe80::4275:e186:85e2:d81f/64 scope link noprefixroute
valid_lft forever preferred_lft forever
3: cni0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 7e:b6:04:22:4f:22 brd ff:ff:ff:ff:ff:ff
inet 10.88.0.1/16 scope global cni0
valid_lft forever preferred_lft forever
inet6 fe80::7cb6:4ff:fe22:4f22/64 scope link
valid_lft forever preferred_lft forever
12: veth2a07dc55@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master cni0 state UP group default
link/ether 42:0d:69:13:89:af brd ff:ff:ff:ff:ff:ff link-netns cni-61ba825e-e596-b2ef-a59f-b0743025e448
inet6 fe80::400d:69ff:fe13:89af/64 scope link
valid_lft forever preferred_lft forever
在上述示例中,主机有一个名为
enp0s3
的接口,其 IP 地址为
192.168.0.33
,连接到外部网络。此外,还创建了一个名为
cni0
的虚拟接口,其 IP 地址为
10.88.0.1
。
在主机上运行的容器中执行相同的
ip
命令,可能会得到以下输出:
# ip a
输出示例:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
3: eth0@if12: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 3e:52:22:4b:e0:d8 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 10.88.0.28/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::3c52:22ff:fe4b:e0d8/64 scope link
valid_lft forever preferred_lft forever
此容器的 IP 地址为
10.88.0.28
。在主机上运行
ping
命令可验证主机和容器是否在同一子网:
# ping 10.88.0.28
输出示例:
PING 10.88.0.28 (10.88.0.28) 56(84) bytes of data.
64 bytes from 10.88.0.28: icmp_seq=1 ttl=64 time=0.056 ms
64 bytes from 10.88.0.28: icmp_seq=2 ttl=64 time=0.039 ms
CNI 配置设置可在主机系统的
/etc/cni/net.d/87-podman-bridge.conflist
文件中找到,默认内容如下:
{
"cniVersion": "0.3.0",
"name": "podman",
"plugins": [
{
"type": "bridge",
"bridge": "cni0",
"isGateway": true,
"ipMasq": true,
"ipam": {
"type": "host-local",
"subnet": "10.88.0.0/16",
"routes": [
{ "dst": "0.0.0.0/0" }
]
}
},
{
"type": "portmap",
"capabilities": {
"portMappings": true
}
}
]
}
可对该文件进行修改,以更改子网地址范围,也可更改插件类型(此示例中设置为
bridge
)来实现不同的网络配置。
12. 在 Cockpit 中管理容器
除了前面介绍的命令行工具,还可使用 Cockpit 网页界面创建和管理 Linux 容器。
假设系统已安装并启用 Cockpit(相关内容可参考 “An Overview of the RHEL 8 Cockpit Web Interface”),且已完成本章开头所述的登录 Red Hat 容器注册表的步骤,登录 Cockpit 并选择 Podman Containers 屏幕。
第一步是下载一个镜像作为容器的基础(若已使用命令行工具下载过镜像,则可跳过此步骤)。点击
Get new image
按钮,在搜索对话框中输入关键字进行搜索。例如,搜索 RHEL 8 通用基础镜像。
找到镜像后,选择它并点击
Download
按钮从注册表中拉取。下载完成后,镜像将出现在镜像列表中。
若要将镜像作为容器运行,点击镜像列表中突出显示的
run
按钮,在弹出的对话框中配置容器。对话框中提供了一些选项,如将主机上的端口映射到容器上的端口(若容器托管 Web 服务器,此选项很有用)、限制分配给容器的内存、指定用作容器存储的卷,还可指定容器启动时要运行的程序。配置完成后,点击
Run
按钮启动容器。
综上所述,在 RHEL 8 上使用容器可借助多种工具和方法,无论是命令行操作还是通过 Cockpit 网页界面,都能方便地创建、管理和操作容器。通过合理运用这些工具和技术,可充分发挥容器的速度和效率优势。
在 RHEL 8 上使用容器
13. 容器操作流程总结
为了更清晰地展示在 RHEL 8 上使用容器的操作流程,以下是一个 mermaid 格式的流程图:
graph LR
A[安装容器工具] --> B[登录 Red Hat 容器注册表]
B --> C[拉取容器镜像]
C --> D[在容器中运行镜像]
D --> E[管理容器]
E --> F[将容器保存为镜像]
F --> G[从本地存储中删除镜像]
E --> H[删除容器]
C --> I[使用 Buildah 构建容器]
I --> J[从头开始构建容器]
D --> K[容器桥接网络配置]
D --> L[在 Cockpit 中管理容器]
这个流程图展示了从容器工具安装到容器管理、镜像操作等一系列步骤,涵盖了前面所介绍的各种操作。
14. 常见问题及解决方法
在使用容器的过程中,可能会遇到一些常见问题,以下是一些问题及对应的解决方法:
| 问题描述 | 可能原因 | 解决方法 |
|---|---|---|
| 拉取镜像失败 | 网络问题、注册表认证失败、镜像不存在 | 检查网络连接;确认 Red Hat 凭证是否正确;检查镜像名称和标签是否正确 |
| 容器无法启动 | 镜像损坏、资源不足、命令参数错误 |
重新拉取镜像;检查系统资源使用情况;检查
podman run
命令的参数
|
| 容器内软件包安装失败 |
网络问题、镜像不支持某些软件包、
dnf
配置错误
|
检查网络连接;确认镜像是否支持要安装的软件包;检查
dnf
的配置文件
|
15. 容器使用的最佳实践
为了更好地使用容器,以下是一些最佳实践建议:
-
镜像管理
:定期清理不再使用的镜像,以节省磁盘空间。使用有意义的镜像名称和标签,方便识别和管理。
-
容器资源管理
:根据容器的实际需求合理分配资源,避免资源浪费或不足。可使用
podman run
命令的相关参数来限制容器的内存、CPU 等资源使用。
-
安全配置
:确保容器运行在安全的环境中,避免使用具有高权限的镜像。定期更新容器内的软件包,以修复安全漏洞。
16. 容器与虚拟机的对比
容器和虚拟机都是实现虚拟化的方式,但它们有一些不同之处,以下是一个简单的对比表格:
| 对比项 | 容器 | 虚拟机 |
|---|---|---|
| 启动速度 | 快,通常只需几秒 | 慢,需要启动完整的操作系统 |
| 资源占用 | 少,共享主机的内核和资源 | 多,需要分配独立的操作系统和资源 |
| 隔离性 | 相对较弱,共享主机内核 | 强,拥有独立的操作系统和内核 |
| 部署难度 | 低,易于快速部署和迁移 | 高,部署和迁移相对复杂 |
17. 未来发展趋势
随着技术的不断发展,容器技术在云计算、大数据等领域的应用越来越广泛。未来,容器技术可能会朝着以下方向发展:
-
更高的性能
:不断优化容器的性能,提高资源利用率和处理速度。
-
更强的安全性
:加强容器的安全机制,保障容器内数据和应用的安全。
-
更广泛的集成
:与其他技术(如 Kubernetes、微服务等)更好地集成,实现更复杂的应用场景。
18. 总结
在 RHEL 8 上使用容器为我们提供了一种高效、灵活的应用部署和管理方式。通过 Podman、Skopeo 和 Buildah 等工具,我们可以方便地完成容器的创建、运行、管理等操作。同时,还可以使用 Cockpit 网页界面进行可视化管理,提高操作的便捷性。
在实际使用过程中,我们需要注意容器的资源管理、安全配置等问题,并遵循最佳实践建议,以充分发挥容器的优势。随着容器技术的不断发展,相信它将在更多领域得到广泛应用。
希望本文能帮助你更好地理解和使用 RHEL 8 上的容器技术,如果你在实践过程中遇到问题,可参考前面提到的常见问题及解决方法,或者查阅相关的技术文档。
超级会员免费看
1681

被折叠的 条评论
为什么被折叠?



