16、在 RHEL 8 上使用容器

在 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 上的容器技术,如果你在实践过程中遇到问题,可参考前面提到的常见问题及解决方法,或者查阅相关的技术文档。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值