跳到内容跳到页面导航:上一页 [access key p]/下一页 [access key n]
documentation.suse.com / 容器指南 / Podman 概述
适用范围 容器指南

6 Podman 概述

Podman 是 Pod Manager 工具的简称。它是一个无守护程序的容器引擎,用于在 Linux 系统上管理 Open Container Initiative (OCI) 容器,可以直接取代 Docker。Podman 的最显著特性是现成地支持无 root 权限容器,可在运行容器时提供更小的攻击面。可以使用 Podman 通过 Dockerfile 和一系列与 Docker 开源引擎相同的命令来创建符合 OCI 标准的容器映像。例如,podman build 命令执行与 docker build 相同的任务。换言之,Podman 可以直接替代 Docker 开源引擎。

从 Docker 开源引擎迁移到 Podman 不需要对既有的工作流程进行任何更改。您无需重构建映像,可以使用完全相同的命令来构建和管理映像,以及运行和控制容器。

Podman 与 Docker 开源引擎的差别体现在两个方面:

  • Podman 不使用守护程序,因此容器引擎在需要时将直接与映像注册表、容器和映像存储交互。

  • Podman 具有本机 systemd 集成功能,允许使用 systemd 来运行容器。Podman 通过 podman generate systemd 命令来支持生成所需的 systemd 单元文件。此外,Podman 可以在容器内部运行 systemd。

  • Podman 无需 root 特权即可创建和运行容器。这意味着 Podman 既能以 root 用户身份运行,也能在非特权环境中运行。此外,非特权用户创建的容器在主机上无法获得高于容器创建者的特权。

  • 可将 Podman 配置为通过读取 /etc/containers/registries.conf 文件来搜索多个注册表。

  • Podman 可以从 Kubernetes 清单部署应用程序

  • Podman 支持在容器内部启动 systemd,并且不要求采取可能存在风险的解决方法。

最后但同样重要的是,Podman 使您能够将容器组织到 Pod 中。Pod 共享同一个网络接口。将一组容器组织到 Pod 中的一个典型用例是运行数据库的容器,以及包含访问数据库的客户端的容器。有关 Pod 的更多信息,请参见第 13.2 节 “包含 Podman 的单容器主机”

6.1 Podman 安装

要安装 Podman,请确保启用 SLE Containers 模块(参见第 5.1 节 “SLE Containers 模块”),并运行命令 sudo zypper in podman。然后运行 podman info 来检查 Podman 是否已成功安装。

默认情况下,Podman 会尝试以当前用户的身份启动容器。对于非特权用户,这意味着以无 root 权限模式启动容器。默认已为 SLE 中所有新建的用户启用了对无 root 权限容器的支持,无需执行额外的步骤。

如果 Podman 无法以无 root 权限模式启动容器,请检查 /etc/subuid 中是否存在当前用户的对应项:

 ❯ grep $(id -nu) /etc/subuid
user:10000:65536

如果未找到该项,请通过以下命令添加所需的子 UID 和子 GID 项:

> sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $(id -nu)

要启用更改,请重引导计算机或停止当前用户的会话。要执行后一项操作,请运行 loginctl list-sessions | grep USER 并记下会话 ID。然后运行 loginctl kill-session SESSION_ID 以停止会话。

以上 usermod 命令会在主机上定义一系列本地 UID,分配给容器中的用户的 UID 将映射到这些 UID。请注意,为不同用户定义的范围不得重叠。同样重要的是,这些范围不能重复使用现有本地用户或组的 UID。默认情况下,在 SLES 15 中使用 useradd 命令添加用户会自动分配子 UID 和子 GID 范围。

使用包含 Podman 的无 root 权限容器时,建议使用 cgroups v2。与 cgroups v2 相比,cgroups v1 在功能方面存在限制。例如,cgroups v1 允许每个用户修改所有现有的控制组,而不仅仅是他们自己的控制组。此外,Podman 无法使用 cgroups v1 和 systemd 日志驱动程序正确读取容器日志。要启用 cgroups v2,请将以下内容添加到内核命令行:systemd.unified_cgroup_hierarchy=1

在 SLES 上以无 root 权限模式运行包含 Podman 的容器可能会失败,因为容器需要对 SCC 身份凭证拥有读取访问权限。例如,使用命令 podman run -it --rm registry.suse.com/suse/sle15 bash 运行容器,然后执行 zypper ref 会导致出现以下错误消息:

Refreshing service 'container-suseconnect-zypp'.
Problem retrieving the repository index file for service 'container-suseconnect-zypp':
[container-suseconnect-zypp|file:/usr/lib/zypp/plugins/services/container-suseconnect-zypp]
Warning: Skipping service 'container-suseconnect-zypp' because of the above error.
Warning: There are no enabled repositories defined.
Use 'zypper addrepo' or 'zypper modifyrepo' commands to add or enable repositories

要解决该问题,请在主机上运行以下命令为当前用户授予所需的访问权限:

> sudo setfacl -m u:$(id -nu):r /etc/zypp/credentials.d/*

注销然后重新登录以应用更改。

要为多个用户授予所需的访问权限,请使用 groupadd GROUPNAME 命令创建一个专用组。然后使用以下命令更改 /etc/zypp/credentials.d/ 目录中的文件的组所有权和权限。

> sudo chgrp GROUPNAME /etc/zypp/credentials.d/*
> sudo chmod g+r /etc/zypp/credentials.d/*

之后,您便可以通过将特定用户添加到这个创建的组来为其授予写入访问权限。

6.1.1 有关无 root 权限容器的提示和技巧

Podman 将用户 ID 重新映射到无 root 权限容器。在以下示例中,Podman 将当前用户重新映射到容器中的默认用户:

❯ podman run --rm -it registry.suse.com/bci/bci-base id
uid=0(root) gid=0(root) groups=0(root)

请注意,即使您是容器中的 root 用户,也无法在容器外部获取超级用户特权。

与主机共享数据时,如果共享的文件属于容器和主机中的不同用户 ID,这种用户重新映射可能会导致不利的负面影响。可以使用命令行标志 --userns=keep-id 来解决该问题,这样可以保留容器中的当前用户 ID:

❯ podman run --userns=keep-id --rm -it registry.suse.com/bci/bci-base id
uid=1000(user) gid=1000(users) groups=1000(users)

与绑定挂载一起使用时,标志 --userns=keep-id 可以提供类似的效果:

 ❯ podman run --rm -it -v $(pwd):/share/ registry.suse.com/bci/bci-base stat /share/
  File: /share/
  Size: 318             Blocks: 0          IO Block: 4096   directory
Device: 2ch/44d Inode: 3506170     Links: 1
Access: (0755/drwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2023-05-03 12:52:18.636392618 +0000
Modify: 2023-05-03 12:52:17.178380923 +0000
Change: 2023-05-03 12:52:17.178380923 +0000
 Birth: 2023-05-03 12:52:15.852370288 +0000

 ❯ podman run --userns=keep-id --rm -it -v $(pwd):/share/ registry.suse.com/bci/bci-base stat /share/
  File: /share/
  Size: 318             Blocks: 0          IO Block: 4096   directory
Device: 2ch/44d Inode: 3506170     Links: 1
Access: (0755/drwxr-xr-x)  Uid: ( 1000/     user)   Gid: ( 1000/     users)
Access: 2023-05-03 12:52:18.636392618 +0000
Modify: 2023-05-03 12:52:17.178380923 +0000
Change: 2023-05-03 12:52:17.178380923 +0000
 Birth: 2023-05-03 12:52:15.852370288 +0000

Podman 将容器的数据存储在存储图根目录中(默认为 ~/.local/share/containers/storage)。由于 Podman 在无 root 权限容器中重新映射用户 ID 的方式,图根目录可能包含不是由当前用户拥有的,而是由子 UID 区域中指派给该用户的用户 ID 拥有的文件。由于这些文件不属于当前用户,因此您可能无法访问它们。

要读取或修改图根目录中的任何文件,请如下所示进入外壳:

 ❯ podman unshare bash

 ❯ id
uid=0(root) gid=0(root) groups=0(root),65534(nobody)

请注意,在启动无 root 权限容器时,podman unsharepodman run 一样执行用户重新映射。您无法通过 podman unshare 获取提升的特权。

请不要修改图根目录中的文件,因为这可能会损坏 Podman 的内部状态,并使容器、映像和卷无法正常运行。

6.1.2 有关无 root 权限容器的注意事项

由于非特权用户无法在 Linux 上配置网络名称空间,因此 Podman 依赖于名为 slirp4netns 的用户空间网络实现。该实现模拟完整的 TCP-IP 堆栈,可能会导致依赖于较高网络传输速率的工作负载出现严重的性能下降。也就是说,当网络传输速率缓慢时,无 root 权限容器会受到影响。

在 Linux 上,非特权用户无法打开端口号小于 1024 的端口。此限制也适用于 Podman,因此默认情况下,无 root 权限容器无法公开端口号小于 1024 的端口。可以使用以下命令消除此限制:

sysctl net.ipv4.ip_unprivileged_port_start=0

或者可以通过以下命令将端口 1024 设为永久端口:

sysctl -w net.ipv4.ip_unprivileged_port_start=0

请注意,这会允许所有非特权应用程序绑定到端口号小于 1024 的端口。

6.1.3 Podman-docker

由于 Podman 与 Docker 开源引擎兼容,因此它提供相同的命令行界面。您还可以安装软件包 podman-docker,以便可以将模拟的 docker CLI 与 podman 配合使用。例如,从注册表提取容器映像的 docker pull 命令会改而执行 podman pulldocker build 命令执行 podman build 等命令

Podman 还具有与 Docker 开源引擎兼容的套接字,可通过以下命令启动该套接字:

 ❯ sudo systemctl start podman.socket

旨在用来与 Docker 开源引擎通讯的应用程序可以使用 Podman 套接字通过 Podman 以透明方式启动容器。Podman 套接字可用于通过 docker compose 启动容器,而无需运行 Docker 开源引擎。

6.2 获取容器映像

6.2.1 配置容器注册表

与 Docker 开源引擎相比,Podman 的其中一项优势是可配置为搜索多个容器注册表。要使 Podman 首先搜索 SUSE 注册表并使用 Docker Hub 作为回退搜索源,请在 /etc/containers/registries.conf 文件中添加以下配置:

unqualified-search-registries = ["registry.suse.com", "docker.io"]

请注意,在 SLE 或 openSUSE 上可以跳过此步骤。在这两个发行套件中,SUSE 注册表和 registry.opensuse.org 的优先级高于 Docker Hub。

6.2.3 下载(提取)映像

podman pull 命令从映像注册表提取映像:

# podman pull <registry>[:<port>]/[<namespace>/]<name>:<tag>

例如

# podman pull registry.suse.com/bci/bci-base

请注意,如果未指定 tag,将使用标记 latest

6.3 重命名映像和映像标记

可以任意标记映像(即设置自定义名称),目的主要是设置一个更直观的名称或者标识特定的映像。

从 registry.suse.com 提取 bci-base 映像:

localhost:~ # podman pull registry.suse.com/bci/bci-base
Trying to pull registry.suse.com/bci/bci-base:latest...
Getting image source signatures
Copying blob bf6ca87723f2 done
Copying config 34578a383c done
Writing manifest to image destination
Storing signatures
34578a383c7b6fdcb85f90fbad59b7e7a16071cf47843688e90fe20ff64a684

列出提取的映像:

localhost:~ # podman images
REPOSITORY                      TAG         IMAGE ID      CREATED        SIZE
registry.suse.com/bci/bci-base  latest      34578a383c7b  22 hours ago   122 MB

将 bci-base 映像重命名为 my-base

podman tag 34578a383c7b my-base
podman images
REPOSITORY                      TAG         IMAGE ID      CREATED        SIZE
registry.suse.com/bci/bci-base  latest      34578a383c7b  22 hours ago   122 MB
localhost/my-base               latest      34578a383c7b  22 hours ago   122 MB

将自定义标记添加到 my-base(假设这是映像版本 1)

podman tag 34578a383c7b my-base:1
podman images
REPOSITORY                      TAG         IMAGE ID      CREATED        SIZE
registry.suse.com/bci/bci-base  latest      34578a383c7b  22 hours ago   122 MB
localhost/my-base               latest      34578a383c7b  22 hours ago   122 MB
localhost/my-base               1           34578a383c7b  22 hours ago   122 MB

请注意,默认标记 latest 仍然存在。

6.4 运行映像

与 Docker 开源引擎类似,Podman 能够以交互模式运行容器,使您可以检查和处理映像。要以交互模式运行 suse/sle15,请使用以下命令:

> podman run --rm -ti suse/sle15

6.5 使用 Podman 构建映像

Podman 可以从 Dockerfile 构建映像。podman build 命令的行为与 docker build 相同,并且接受相同的选项。

Podman 的配套工具 Buildah 提供了另一种构建映像的方式。有关 Buildah 的更多信息,请参见第 14 章 “Buildah 概述