Podman 初学者教程
当我们谈论容器时,我们想到的默认工具是Docker。但是在 Docker 出现之后,容器空间有了很多发展,特别是在容器安全方面。Podman 是解决安全问题的项目之一。
什么是Podman?
Podman是一种符合OCI标准的容器管理工具,它提供与 Docker 类似的功能来管理容器。
podman 的最佳特性之一是它能够运行rootless containers。rootless containers是在没有root 权限(普通用户)的情况下运行和管理容器的概念。从安全的角度来看,无根容器通过不允许根访问添加了额外的安全层,即使容器被攻击者破坏也是如此。
Podman 也是无守护进程的(与 docker 不同),这意味着它没有守护进程并直接与 runc 交互(运行基于 OCI 规范的容器)。在文章的最后,我添加了Docker 和 Podman 之间的区别。
另外,假设 Linux 中有两个用户。用户 a和用户 b。user-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 配置有两个容器注册表。
您可以在以下文件中找到默认的 Podman 容器注册表配置。
/etc/containers/registries.conf
您可以向此配置添加自定义或私有容器注册表。例如,google 容器注册表、AWS ECR、自托管私有注册表等。
如果你想使用注册中心的其他私有容器镜像,你可以使用命令登录到注册中心podman。例如,要登录到 docker hub,
podman login docker.io
登录后,您将能够使用podman命令从 docker hub 中拉取容器镜像
如果您希望为特定用户提供不同的注册表配置,您可以registries.conf在用户目录中创建单独的容器注册表信息。
$HOME/.config/containers/registries.conf
Podman 容器存储
每个系统用户都有自己的容器存储。这意味着,如果您尝试从不同的用户登录中提取image,它会从远程注册表中提取image而不是本地image。
例如,
- 对于root 用户,容器存储在
/var/lib/containers/storage目录中 - 对于其他用户,容器存储在
$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文件夹内,您将看到一个Dockerfile和index.html 文件。
让我们使用 podman 构建容器镜像。该命令类似于 docker 命令。
podman build -t scriptcamp/nginx .
现在,让我们将image推送到容器注册表。确保您已登录到容器注册表以推送image。我在这里使用 dockerhub。
podman push scriptcamp/nginx
使用 Podman 创建 Pod
在本节中,我们将学习如何使用 Podman 创建 Pod。Podman 的高级功能之一是它能够创建类似于 Kubernetes pod 的 pod。Pod 是一个单元,您可以在其中拥有一个或多个容器。
这是您可以做的。
- 创建一个空 pod: 当您创建一个空 pod 时,Podman 会分配一个基础容器k8s.gcr.io/pause来保存命名空间并允许与 pod 中的其他容器通信。
- 您可以在 pod 中添加和删除容器。
- 您可以在 pod 中创建完整的应用程序堆栈。
- 您可以在 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 系统。
Docker 与 Podman
如果您想知道 Podman 与 docker 有何不同,下表可帮助您了解一些关键差异。
| Podman | Docker |
|---|---|
| Podman 是无守护进程的 | Docker 有一个守护进程 (containerd)。docker CLI 与守护进程交互以管理容器。 |
| Podman 直接通过 runc 与 Linux 内核交互 | Docker守护进程拥有所有运行容器的子进程 |
| Podman 可以部署具有多个容器的 pod。可以在 Kubernetes 中使用相同的 pod 清单。此外,您可以将 Kubernetes pod 清单部署为 Podman pod。 | Docker中没有pod的概念 |
| 无需任何额外配置即可运行无根容器。您可以使用 root 或非特权用户运行容器。 | Docker 无根模式需要额外的配置。 |
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初学者教程。