在这个针对初学者和老手的 podman 教程中,一步步的从开始使用 podman 到探索所有 Podman 功能。
当我们谈论容器时,我们首先想到的默认工具就是Docker。但自从 Docker 诞生以来,容器领域已经有了很多发展,特别是在容器安全方面。Podman 是解决安全问题的项目之一。
以下是您将从本指南中学到的内容。
什么是PodMan?
Podman是一款符合OCI标准的容器管理工具,提供与 Docker 类似的容器管理功能。
podman 的最佳功能之一是它能够运行无根容器 。无根容器是在没有根权限(普通用户)的情况下运行和管理容器的概念。从安全角度来看,无根容器即使在容器受到攻击者破坏的情况下也不允许根访问,从而增加了额外的安全层。您可以在此处了解无根容器的优点。
注意: Docker 还支持无根模式,但有一些限制。您可以在这里阅读相关内容。
Podman 也是无守护进程的(与 docker 不同),这意味着它没有守护进程并直接与 runc 交互(运行基于 OCI 规范的容器)。在文章的最后,我补充了Docker 和 Podman 之间的区别。
另外,假设 Linux 中有两个用户。用户 a 和用户 b 。用户 a 使用 podman创建的容器不能被用户 b修改,反之亦然。
podman 的另一个有趣且高级的功能是在 Pod 中运行容器。与Kubernetes Pod类似,您可以使用 Podman 在本地创建多容器 Pod。您可以将 podman pod 导出为 Kubernetes 清单,并使用 Kubernetes pod 清单来部署 podman pod。
安装 Podman
前往官方podman 安装文档。在这里您可以找到 Windows、MAC 和 Linux 版本的所有安装命令。
注意:对于 Windows 和 Mac,podman 需要虚拟机来部署容器。
我使用 Ubuntu 20.10 进行测试。对于Debian 11 和 ubuntu 20.10 或更高版本,您可以使用以下步骤。
arduino
sudo apt-get install runc -y
sudo apt-get -y install podman
对于 CentOS 7,
sudo yum -y install podman
对于 MAC,安装 Podaman,然后 使用 podman machine 命令初始化基于QEMU的虚拟机。
csharp
brew install podman
podman machine init
podman machine start
安装后,使用以下命令验证安装。
podman version
Podman 容器注册表配置
默认情况下,Podman 配置有两个容器注册表。
您可以在以下文件中找到默认的 Podman 容器注册表配置。
bash
/etc/containers/registries.conf
您可以将自定义或私有容器注册表添加到此配置。例如,Google容器注册表、AWS ECR、自托管私有注册表等。
如果您想使用registry中的其他私有容器镜像,可以使用命令登录registry podman
。例如,要登录 docker hub,
lua
podman login docker.io
登录后,您将能够使用podman
命令从 docker hub 中提取容器镜像
如果您希望为特定用户拥有不同的注册表配置,您可以registries.conf
在用户目录中创建单独的容器注册表信息。
bash
$HOME/.config/containers/registries.conf
Podman 容器存储
每个系统用户都有自己的容器存储。这意味着,如果您尝试从不同的用户登录中提取映像,它将从远程注册表而不是本地映像中提取映像。
例如,
- 对于root 用户,容器存储在
/var/lib/containers/storage
目录中 - 对于其他用户,容器存储在
$HOME/.local/share/containers/storage/
目录 中
使用 Podman 管理容器
您可以像使用 docker 一样管理容器。但是,我们将使用 podman 作为带有类似于 docker 标志的命令,而不是 docker 命令。此外,您可以使用任何没有 sudo 权限的用户运行 podman 命令。
首先,让我们尝试拉取图像。默认情况下,podman 首先在quay.io 中搜索镜像,然后在docker.io 中搜索。如果quay.io中不存在映像,podman 会在 docker.io 中搜索并拉取该映像。因此,最好指定注册表端点的完整映像名称。例如,
bash
podman pull docker.io/nginx
podman pull quay.io/quay/busybox
让我们从 dockerhub 注册表运行 Nginx 容器。以下命令运行具有主机端口映射的 Nginx 容器8080
。
css
podman run --name docker-nginx -p 8080:80 docker.io/nginx
如果您看到的话,上面的 podman 命令相当于 docker 命令和标志。
在无根模式(普通用户模式)下不能使用低于 1024 的端口。因为普通用户容器命名空间确实具有映射这些端口的权限。如果您想使用 podman 映射小于 1024 的主机端口,您应该以 root 用户或使用 sudo 权限运行 podman,如下所示。
css
sudo podman run --name docker-nginx -p 80:80 docker.io/nginx
您可以使用以下命令检查映射的端口。-l
flat 返回最新容器的详细信息。
podman port -l
您可以使用检查命令检查容器。
podman inspect -l
其他停止、移除和删除容器的命令与 docker 命令的工作方式相同。
举几个例子,
xml
podman images
podman ps
podman ps -a
podman stop <container-name>
podman rm <container-name>
运行 help 命令以了解所有可用的 podman 命令。
bash
podman --help
使用 Podman 构建容器镜像
让我们尝试使用自定义 HTML 文件构建 Nginx 的容器映像。我在 GitHub 存储库中有 Dockerfile 和 HTML 文件。
让我们将 repo 和 cd 克隆到 repo nginx-image目录中。
bash
git clone https://github.com/scriptcamp/podman.git
cd podman/nginx-image
在nginx-image
文件夹内,您将看到一个Dockerfile
和index.html
文件。
让我们使用 podman 构建容器镜像。该命令与 docker 命令类似。
bash
podman build -t scriptcamp/nginx .
现在,让我们将映像推送到容器注册表。确保您已登录容器注册表以推送映像。这里我使用的是dockerhub。
bash
podman push scriptcamp/nginx
使用 Podman 创建 Pod
在本节中,我们将学习如何使用 Podman 创建 pod。Podaman 的高级功能之一是它能够创建类似于 Kubernetes Pod 的 Pod。Pod 是一个可以拥有一个或多个容器的单元。
这是您可以做的。
- **创建空 pod:**当您创建空 pod 时,Podman 会分配一个基础容器_k8s.gcr.io/pause_来保存命名空间并允许与 pod 中的其他容器进行通信。
- 您可以在 Pod 中添加和删除容器。
- 您可以在 Pod 中创建完整的应用程序堆栈。
- 您可以在 Pod 内有选择地启动和停止容器。
现在让我们看一下示例。
要了解所有可用的 podman pod 命令,只需运行 help 命令即可。
bash
podman pod --help
创建一个空 Pod
让我们创建一个空的 Pod。如果您不指定该--name
标志,podman 将创建一个具有随机名称的 pod。
lua
podman pod create --name demo-pod
让我们列出创建的 Pod。
bash
podman pod ls
以下命令列出 pod 中的所有容器。对于空 Pod,将k8s.gcr.io/pause
添加一个容器。
css
podman ps -a --pod
将容器添加到 Podman Pod
让我们向空 pod 添加一个 Nginx 容器。如果运行以下命令后列出容器,您将看到 Nginx 容器添加到demo-pod
css
podman run -dt --pod demo-pod nginx
启动、停止和删除 Podman Pod 内的容器
您可以使用与删除具有 ID 的容器相同的命令来启动、停止和从 podman pod 中删除容器。
首先使用 podman 命令列出 pod 中的容器,并使用以下命令和容器 ID。
python
podman start <continer-id>
podman stop <continer-id>
podman rm <continer-id>
使用容器创建 Pod
我们可以使用单个命令创建一个 Pod 并添加容器。让我们使用 Nginx 容器创建一个 pod,该容器具有8080
.
arduino
podman run -dt --pod new:frontend -p 8080:80 nginx
如果您访问VM IP上的8080端口,您应该能够看到Nginx主页。
启动、停止和删除 Pod
您可以使用容器 ID/名称选择并停止 pod 内的各个容器,也可以使用以下命令立即停止所有容器。
xml
podman pod stop <podname>
podman pod start <podname>
要删除 pod,首先停止 pod 中的所有容器,然后运行,
bash
podman pod rm <podname>
-f
或者,您可以使用flag强行删除 pod,而不停止容器
bash
podman pod rm -f <pod-name>
多容器应用程序堆栈
您可以在单个 podman pod 中拥有多容器应用程序堆栈。这有助于在本地开发和测试应用程序。
例如,如果您有应用程序和数据库,则可以在同一个 pod 中拥有应用程序和数据库容器。您可以在需要时随时销毁和调出堆栈。类似于 docker-compose 的东西。
应用程序和数据库容器都可以使用本地主机相互通信。我将在博客中单独介绍这个实现。
从 Podman Pod 定义生成 Kubernetes YAML
Podman 的另一个有趣的功能是您可以从 podman pod 生成 Kubernetes pod YAML。这是一个工作功能,但仍在开发中。
首先,让我们使用 Nginx 容器部署一个名为 webserver 的 pod。
arduino
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。首先,我们需要删除现有的 Webserver pod。webserver.yaml
bash
podman pod rm -f webserver
让我们使用以下命令导入 podwebserver.yaml
podman play kube webserver.yaml
现在,让我们尝试导入 Kubernetes YAML。将以下 Kubernetes 清单保存为nginx.yaml
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 系统。
Docker 与 Podman
如果您想知道 Podman 与 docker 有何不同,下表可以帮助您了解一些关键差异。
PodMan | Docker |
---|---|
Podman 是无守护进程的 | Docker 有一个守护进程(containerd)。docker CLI 与守护进程交互来管理容器。 |
Podman直接通过runc与Linux内核交互 | Docker守护进程拥有运行容器的所有子进程 |
Podman 可以部署具有多个容器的 Pod。相同的 pod 清单可以在 Kubernetes 中使用。此外,您还可以将 Kubernetes Pod 清单部署为 Podman Pod。 | Docker中没有pod的概念 |
无需任何额外配置即可运行无根容器。您可以使用 root 或非特权用户运行容器。 | Docker 无根模式需要额外的配置。 |
Podman VS Buildah
当您开始学习或研究 podman 时,您将阅读有关Buildah 的内容。这两个项目最初都是由 Redhat 创建的。
您可能会对 Podman 和 Buildah 项目感到困惑。Podman 在幕后使用 Buildah 进行运行和构建操作。阅读这个官方 podman 博客,其中解释了Podman 和 Buildah之间的区别。
Podman 错误和问题
以下是我在使用 Podman 进行实践时遇到的一些错误和问题。
端口映射错误
如果您尝试映射特权端口,您可能会收到以下错误。如果您想以非 root 用户身份运行 Podman,请始终使用非特权端口。
vbnet
Error: error from slirp4netns while setting up port redirection: map[desc:bad request: add_hostfwd: slirp_add_hostfwd failed]
如果您没有runc
安装,可能会出现以下错误。
javascript
Error: default OCI runtime "runc" not found: invalid argument
图像错误
如果您没有指定正确的镜像名称,Podman 将抛出以下错误。
vbnet
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 ,您应该正确指定映像名称。
例如,podman pull busybox
,将引发错误。但是,podman pull quay/busybox
工作时没有任何错误。
Pod 错误
如果您尝试添加具有在 Pod 创建过程中未添加的端口的容器,您将收到以下错误。
vbnet
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。
arduino
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 列出容器,您将收到以下错误。
javascript
Error: no pod with name or ID webserver found: no such pod
结论
在本podman 教程中,我解释了开始使用 Podman 管理容器的所有基本概念。
如果您已经在 Mac 和 Windows 上广泛使用 Docker 桌面,那么 podman 并不是可以取代它的东西。然而,podman 有它自己的好处。
但毫无疑问,是时候停止将 Docker 视为容器事实上的标准了。
您可能正在使用 docker 并正在寻找其他有关容器管理的工具,或者刚刚听说过 podman。无论哪种方式,请在下面的评论中告诉我您的想法。