Podman 初学者教程

5,715 阅读11分钟

Podman 初学者教程

当我们谈论容器时,我们想到的默认工具是Docker。但是在 Docker 出现之后,容器空间有了很多发展,特别是在容器安全方面。Podman 是解决安全问题的项目之一。

什么是Podman?

Podman是一种符合OCI标准的容器管理工具,它提供与 Docker 类似的功能来管理容器。

podman 的最佳特性之一是它能够运行rootless containers。rootless containers是在没有root 权限(普通用户)的情况下运行和管理容器的概念。从安全的角度来看,无根容器通过不允许根访问添加了额外的安全层,即使容器被攻击者破坏也是如此。

Podman 也是无守护进程的(与 docker 不同),这意味着它没有守护进程并直接与 runc 交互(运行基于 OCI 规范的容器)。在文章的最后,我添加了Docker 和 Podman 之间的区别。

另外,假设 Linux 中有两个用户。用户 a用户 buser-a使用 podman创建的容器不能被user-b修改,反之亦然。

podman 的另一个有趣且高级的功能是在 Pod 中运行容器。与Kubernetes pod类似,您可以使用 Podman 在本地创建多容器 pod。您可以将 podman pod 导出为 Kubernetes 清单,并使用 Kubernetes pod 清单来部署和 podman pod。

Podman Github 教程

这里有一个包含一些示例的Podman Github 存储库。我将不断更新有关资源和示例。

git clone https://github.com/techiescamp/podman

该存储库包含一个 Vagrantfile,您可以使用它来学习和测试 podman。Podman 和 runc 在启动vagrant VM时安装。它使用 ubuntu 20.10 基本映像。

前往官方的podman 安装文档。在这里您可以找到适用于 Windows、MAC 和 Linux 版本的所有安装命令。

注意:对于 Windows 和 Mac,podman 需要一个虚拟机来部署容器。

我正在使用 Ubuntu 20.10 进行测试。您可以对 Debian 11 和 ubuntu 20.10 或更高版本使用以下步骤。

sudo apt-get install runc -y
sudo apt-get -y install podman

对于 centos 7,

sudo yum -y install podman

对于 MAC 安装 Podaman,然后 使用 podman machine 命令初始化基于QEMU的虚拟机。

brew install podman
podman machine init
podman machine start

安装后,使用以下命令验证安装。

podman version

Podman 容器注册表配置

默认情况下,Podman 配置有两个容器注册表。

  1. quay.io
  2. docker.io

您可以在以下文件中找到默认的 Podman 容器注册表配置。

/etc/containers/registries.conf

podman 默认容器注册表。

您可以向此配置添加自定义或私有容器注册表。例如,google 容器注册表、AWS ECR、自托管私有注册表等。

如果你想使用注册中心的其他私有容器镜像,你可以使用命令登录到注册中心podman。例如,要登录到 docker hub,

podman login docker.io

登录后,您将能够使用podman命令从 docker hub 中拉取容器镜像

如果您希望为特定用户提供不同的注册表配置,您可以registries.conf在用户目录中创建单独的容器注册表信息。

$HOME/.config/containers/registries.conf

Podman 容器存储

每个系统用户都有自己的容器存储。这意味着,如果您尝试从不同的用户登录中提取image,它会从远程注册表中提取image而不是本地image。

例如,

  1. 对于root 用户,容器存储在 /var/lib/containers/storage目录中
  2. 对于其他用户,容器存储在$HOME/.local/share/containers/storage/目录 中

使用 Podman 管理容器

您可以像使用 docker 一样管理容器。但是,我们将使用 podman 作为带有类似于 docker 标志的命令,而不是 docker 命令。此外,您可以使用没有 sudo 权限的任何用户运行 podman 命令。

首先,让我们尝试拉取image。默认情况下,podman 首先在quay.io中搜索image,然后在docker.io中搜索image。如果镜像不在quay.io中,podman 会在 docker.io 中搜索并拉取镜像。所以最好在注册表端点指定完整的image名称。例如,

podman pull docker.io/nginx
podman pull quay.io/quay/busybox

让我们从 dockerhub 注册表运行一个 Nginx 容器。以下命令使用8080主机端口映射运行 Nginx 容器。

podman  run --name docker-nginx -p 8080:80 docker.io/nginx

如果你看到,上面的 podman 命令等同于 docker 命令和标志。

您不能在非root模式(普通用户模式)下使用低于 1024 的端口。因为普通用户容器命名空间确实有权限映射那些端口。如果要使用 podman 映射小于 1024 的主机端口,则应以 root 用户身份或使用 sudo 权限运行 podman,如下所示。

sudo podman run --name docker-nginx -p 80:80 docker.io/nginx

您可以使用以下命令检查映射的端口。-l flat 返回最新容器的详细信息。

podman port -l

您可以使用 inspect 命令检查容器。

podman inspect -l

其他用于停止、移除和删除容器的命令与 docker 命令的工作方式相同。

几个例子,

podman images
podman ps
podman ps -a
podman stop <container-name>
podman rm <container-name>

运行 help 命令以了解所有可用的 podman 命令。

podman --help

使用 Podman 构建容器镜像

让我们尝试使用自定义 HTML 文件构建 Nginx 的容器映像。我在 GitHub 存储库中有 Dockerfile 和 HTML 文件。

让我们将 repo 和 cd 克隆到 repo nginx-image目录中。****

git clone https://github.com/scriptcamp/podman.git
cd podman/nginx-image

nginx-image文件夹内,您将看到一个Dockerfileindex.html 文件。

让我们使用 podman 构建容器镜像。该命令类似于 docker 命令。

podman build -t scriptcamp/nginx .

现在,让我们将image推送到容器注册表。确保您已登录到容器注册表以推送image。我在这里使用 dockerhub。

podman push scriptcamp/nginx

使用 Podman 创建 Pod

在本节中,我们将学习如何使用 Podman 创建 Pod。Podman 的高级功能之一是它能够创建类似于 Kubernetes pod 的 pod。Pod 是一个单元,您可以在其中拥有一个或多个容器。

这是您可以做的。

  1. 创建一个空 pod: 当您创建一个空 pod 时,Podman 会分配一个基础容器k8s.gcr.io/pause来保存命名空间并允许与 pod 中的其他容器通信。
  2. 您可以在 pod 中添加和删除容器。
  3. 您可以在 pod 中创建完整的应用程序堆栈。
  4. 您可以在 pod 内有选择地启动和停止容器。

现在让我们看看例子。

要了解所有可用的 podman pod 命令,只需运行 help 命令。

podman pod --help

创建一个空 Pod

让我们创建一个空的 pod。如果您不指定该--name标志,podman 将创建一个具有随机名称的 pod。

podman pod create --name demo-pod

让我们列出创建的 pod。

podman pod ls

以下命令列出 pod 中的所有容器。对于空的 pod,将k8s.gcr.io/pause添加一个容器。

podman ps -a --pod

将容器添加到 Podman Pod

让我们向空 pod 添加一个 Nginx 容器。如果在运行以下命令后列出容器,您将看到 Nginx 容器已添加到demo-pod

podman run -dt --pod demo-pod  nginx

启动、停止和删除 Podman Pod 内的容器

您可以使用与删除容器及其 ​​ID 相同的命令从 podman pod 启动、停止和删除容器。

首先使用 podman 命令列出 pod 中的容器,然后使用以下命令和容器 ID。

podman start <continer-id>
podman stop <continer-id>
podman rm <continer-id>

使用容器创建 Pod

我们可以创建一个 pod 并使用单个命令添加容器。让我们创建一个带有 Nginx 容器的 pod,主机端口映射为8080.

podman run -dt --pod new:frontend -p 8080:80 nginx

如果访问虚拟机 IP 上的 8080 端口,应该可以看到 Nginx 主页。

启动、停止和删除 Pod

您可以使用容器 ID/名称选择并停止 pod 中的单个容器,也可以使用以下命令一次停止所有容器。

podman pod stop <podname>
podman pod start <podname>

要删除 pod,首先,停止 pod 中的所有容器,然后运行,

podman pod rm <podname>

-f 或者您可以强制删除 pod 而无需使用flag停止容器

podman pod rm -f <pod-name>

多容器应用栈

您可以在单个 podman pod 中拥有多容器应用程序堆栈。这有助于在本地开发和测试应用程序。

例如,如果您有一个应用程序和一个数据库,您可以在同一个 pod 中有一个应用程序和一个数据库容器。您可以在需要时随时销毁和调出堆栈。类似于 docker-compose 的东西。

应用程序和数据库容器都可以使用本地主机相互通信。我将在博客中单独介绍此实现。

从 Podman Pod 定义生成 Kubernetes YAML

Podman 的另一个有趣的特性是您可以从 podman pod 生成 Kubernetes pod YAML。这是一个有效的功能,但仍在开发中。

首先,让我们用一个 Nginx 容器部署一个名为 webserver 的 pod。

podman run -dt --pod new:webserver -p 8080:80 nginx

现在要为 podman pod 生成 Kubernetes YAML,我们将使用generate kube带有 pod 名称的标志,如下所示。

podman generate kube webserver

您可以使用重定向将生成的 YAML 定向到文件。

podman generate kube webserver >> webserver.yaml

从 YAML 创建 Podman Pod

如果您有 pod YAML 文件,则可以使用play kube标志将其作为 Podman pod 导入并运行。

例如,我们将使用上一节中生成的 Pod 来运行它。首先,我们需要删除现有的网络服务器 pod。webserver.yaml

podman pod rm -f webserver

让我们使用webserver.yaml

podman play kube webserver.yaml

现在,让我们尝试导入 Kubernetes YAML。将以下 Kubernetes 清单另存为nginx.yaml

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: webserver
    image: docker.io/nginx:latest
    ports:
    - containerPort: 80

让我们将其导入为 podman pod。

podman play kube nginx.yaml

现在,如果您列出 pod,您可以看到一个正在运行的 Nginx pod。

Podman 桌面

Podman Desktop 是用于管理 podman 容器的 GUI 工具。它适用于 Windows、MAC 和 Linux 系统。

您可以从此处下载并安装 Podman Desktop

Docker 与 Podman

如果您想知道 Podman 与 docker 有何不同,下表可帮助您了解一些关键差异。

PodmanDocker
Podman 是无守护进程的Docker 有一个守护进程 (containerd)。docker CLI 与守护进程交互以管理容器。
Podman 直接通过 runc 与 Linux 内核交互Docker守护进程拥有所有运行容器的子进程
Podman 可以部署具有多个容器的 pod。可以在 Kubernetes 中使用相同的 pod 清单。此外,您可以将 Kubernetes pod 清单部署为 Podman pod。Docker中没有pod的概念
无需任何额外配置即可运行无根容器。您可以使用 root 或非特权用户运行容器。Docker 无根模式需要额外的配置。

podman 教程:docker 与 podman

Podman 与 Buildah

当您开始学习或研究 podman 时,您将阅读有关Buildah 的内容。这两个项目最初都是由 Redhat 创建的。

您可能会对 Podman 和 Buildah 项目感到困惑。Podman 在幕后使用 Buildah 进行运行和构建操作。阅读这个解释Podman 和 Buildah之间区别的官方 podman 博客。

Podman 错误和问题

以下是我在实际操作 Podman 时遇到的一些错误和问题。

端口映射错误

如果您尝试映射特权端口,您可能会收到以下错误。如果您想以非 root 用户身份运行 Podman,请始终使用非特权端口。

Error: error from slirp4netns while setting up port redirection: map[desc:bad request: add_hostfwd: slirp_add_hostfwd failed]

如果您尚未runc安装,您可能会收到以下错误。

 Error: default OCI runtime "runc" not found: invalid argument

Image错误

如果您没有指定正确的Image名称,Podman 将抛出以下错误。

Trying to pull quay.io/busybox...
  error parsing HTTP 404 response body: invalid character '<' looking for beginning of value: "<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">\n<title>404 Not Found</title>\n<h1>Not Found</h1>\n<p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>\n"

它通常发生在 quay.io 上,因为与 docker 不同,对于 quay.io ,您应该正确指定Image名称。

例如,podman pull busybox, 将抛出错误。但是,podman pull quay/busybox工作没有任何错误。

Pod 错误

如果您尝试添加一个容器,其端口在 Pod 创建期间未添加,您将收到以下错误。

Error: invalid config provided: published or exposed ports must be defined when the pod is created: network cannot be configured when it is shared with a pod

如果您尝试删除正在运行容器的 pod,您将收到以下错误。首先,您需要停止所有容器,然后删除 pod。

Error: pod 9e31de31950664702f21 has containers that are not ready to be removed: cannot remove container 3d10007e844a5aea3c7805fb0ee986b0b4c2cedd66c0996d0bff9f53ba1c0b57 as it is running - running or paused containers cannot be removed without force: container state improper

有时您可能会使用特定用户部署容器,如果您尝试使用不同的用户或使用 sudo 列出容器,您将收到以下错误。

Error: no pod with name or ID webserver found: no such pod

结论

在本podman 教程中,我解释了开始使用 Podman 管理容器的所有基本概念。

如果您已经在 mac 和 windows 上广泛使用 Docker 桌面,那么 podman 不是可以替代它的东西。但是,podman 有其自身的优势。

但可以肯定的是,在容器方面,是时候停止将 Docker 视为事实上的标准了。

您可能正在使用 docker 并正在寻找另一种容器管理工具,或者只是听说过 podman。无论哪种方式,请在下面的评论中告诉我您的想法。

另外,如果你正在学习 Kubernetes,你可以查看我的 Kubernetes初学者教程。