zzxworld

Podman 安装和使用初体验

Docker 是我日常开发工作中离不开的环境工具软件。不仅是本地搭建开发环境,在一些项目的线上部署中也会用到。不过最近我注意到 Docker 背后公司的一些举动有些不太对劲,为以防万一,我开始提前了解它的替代品:Podman。

起因

开始 Podman 的介绍之前,先说说 Docker 让我觉得不对劲的事情。为了看起来直观一点,我列了个简单的时间线:

  • 2015:获得大量融资,创始人员在发展方向上「是选择走社区化还是走商业化」产生了路线分歧。
  • 2018:创始人 Solomon Hykes 离职。
  • 2019:Docker 公司被 Mirantis 收购。
  • 2021:Docker Desktop 开始向大公司用户收费。

我之前一直认为 Docker 有社区版,所以没太在意它背后的商业行为。而且上面发生的任何一件事,单独看好像都没什么大不了的。但如果连在一起,就有点意思了。

危言耸听的总结一下:Docker 已经经历了资本进入,创始人决裂,公司易手。现在为了想赚钱的法子,开始薅程序员开发者的羊毛。

Docker Desktop 是什么?简单说就是一个靠虚拟机运行 Docker 的界面化容器管理软件。我之前在 macOS 系统上为了使用 Docker 安装过。但基于这个软件实现的 Docker 环境因为虚拟机文件系统的原因,性能实在太弱。所以我放弃了 macOS 系统,回到了 Linux。Linux 系统上不需要这个软件,大规模应用 Docker 的线上环境也是。

Docker Desktop 收费对我来说目前虽然没有任何影响。但这是一个信号,意味着接下来 Docker 为了利润进行更加深入尝试的可能性会很大。

所以我决定开始了解 Docker 的开源替代品: Podman。

安装 Podman

作为 Docker 的替代品,Podman 的操作和 Docker 高度兼容。按官方文档的说法,直接把 podman 映射为 docker 命令来使用也没问题。但我觉得没必要,同样还是 6 个字母,没有减轻任何输入负担。而且在运行方式上, Docker 依赖于守护进程,Podman 不需要守护进程。这种区别决定了所谓的高度兼容,一定会存在一些使用方式上的差异。为了避免认知上的混淆,我觉得还是有必要把 Podman 当成一个全新的工具。

在 Arch Linux 上安装 Podman 很简单,直接使用 Pacman 包管理命令:

sudo pacman -S podman

然后编辑 /etc/containers/registries.conf 文件,添加一个可用的容器镜像库地址:

unqualified-search-registries = ["docker.io"]

接着就可以正常运行容器了:

sudo podman run --rm hello-world

执行结果如下:

Screenshort 1

使用普通帐号

我不太习惯以 sudo 特权方式来运行容器,而且也没必要。Docker 可以通过把当前帐号加入 docker 用户组的方式来解决这个问题。Podman 稍微麻烦一点,因为它有一个用户命名空间的概念。

关于 Podman 用户命名空间,我目前还不是十分明白。浅显的一点理解是针对运行中容器的权限管理机制。可以防止容器进程出现逾越权限的安全隐患。更具体的内容还需要后面了解并实践,所以还是先分享操作过程。

先看看不用 sudo 执行的结果:

Screenshort 2

提示 user namespace 中的用户 ID 和用户组 ID 不可用。最后还提示要检查 /etc/subuid/etc/subgid 这两个文件。系统默认情况下没有它们,定义所谓的用户命名空间就是要创建这两个文件。

先创建这两个空文件:

sudo touch /etc/subuid /etc/subgid

目前没有任何内容,给它们填充点东西:

sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $USER

再执行以下命令使文件中的用户映射信息在容器中生效:

podman system migrate

然后再次以普通用户运行容器就没问题了。

Screenshort 3

小于 1024 端口的映射

以上面运行的 Nginx 容器为例,如果想映射容器内的 80 端口到本机的 80 端口,会出现以下报错:

Screenshort 4

这个报错的提示很详细,指明了问题的原因和解决方案。Linux 系统限制了非特权用户可以使用的最小端口。也就是默认只能选择 1024 往上的。如果要使用 80 这种小于 1024 的端口号,只有两个方案:

  1. 使用 sudo 以特权方式执行命令。
  2. 修改 /etc/sysctl.conf 文件的 net.ipv4.ip_unprivileged_port_start 配置项。比如把值改成 80。

这两种方案需要自己根据情况来选择,我的建议是如果能用特权方式来执行的就优先选择这个方法,情况实在特殊再考虑改系统配置的方案。

开机启动

Docker 因为有守护进程,所以自身就能实现开机启动功能。Podman 没有守护进程,需要配合 Systemd 来实现。

还是以运行 Nginx 容器来举例,先把容器运行起来:

sudo podman run --rm -p 80:80 --name nginx nginx:alpine

运行的命令加了一个 --name 参数,并定义了名称为 nginx ,这是为了方便后面生成 Systemd 配置文件。

容器运行成功后,执行下面的命令生成 Systemd 的配置文件:

sudo podman generate systemd --new nginx > nginx.service
sudo mv nginx.service /usr/lib/systemd/system/

然后就可以通过 systemctl 命令来管理这个容器开机自启动了。

总结

从我目前的尝试来看,Podman 在本地开发环境下替代 Docker 问题不大。只是目前这个用户命名空间的概念还需要再了解一下。

和 Docker 依赖 Docker Engine 守护进程的方式对比一下,我也更喜欢 Podman 这种无守护进程的执行方式。不仅节省系统资源,而且也让容器进程的跟踪溯源更加清晰明了。

喜欢归喜欢,关键还是需要用起来。目前我已经开始在尝试了,应该还会碰到一些其他的问题,等碰到了再补充到本文。