2025年了,要不要试试Podman?(转载自知乎)

2025年了,要不要试试Podman?(转载自知乎)

原文链接:https://zhuanlan.zhihu.com/p/22886116297

自从卸载Docker Desktop后,我一直在使用Colima。过去这三年中,它一直稳定可靠。但随着时间推移,我也逐渐发现了一些问题:Colima依然依赖Docker作为容器引擎,而且它基于第三方的Lima虚拟化方案,显得有些冗余和陈旧。偶然间我看到了Podman,它充满着新鲜感:

独立引擎:与Colima依赖Docker引擎不同,Podman采用了自己的开源容器引擎,完全脱离Docker生态。这对我来说是全新的尝试。

Daemonless:Podman的无守护进程设计节省了系统资源,性能更好。

更简单的工具链:相比于Colima需要借助Lima来实现虚拟化,Podman使用自己的Podman Machine工具。

兼容性:Podman与Docker CLI完全兼容,能够无缝接入现有工作流程。

说干就干。不过动手之前,我们先深入了解一下Podman与Colima在底层实现上的区别。

提示:本文阅读时长15分钟。

架构对比

首先,所有的容器方案,都是基于Linux,所以在macOS上需要运行虚拟机。最常见的虚拟机有QEMU、Apple原生的vz和applehv。vz是macOS原生的虚拟化技术Virtualization Framework。目前Lima和Docker Desktop都默认使用vz。而applehv是Apple hypervisor,据说是vz的底层技术,Podman使用applehv。

在虚拟机里运行容器引擎,Docker使用守护进程dockerd,通过容器运行时containerd调用更低级别容器运行时runc。Podman则直接调用自家的容器运行时crun(也支持runc),据说crun比runc快50%,对资源的要求也更低。这些容器运行时都符合OCI标准,所以都可以运行Docker镜像。

此外,还有专门管理虚拟机环境的工具,用来下载Linux镜像、启动虚拟机。Podman方案使用Podman Machine,而Colima方案依赖Lima。

还有命令行工具,Podman方案采用的是Podman Remote,通过SSH调用虚拟机内的Podman。而Colima使用Docker CLI。Podman CLI特意模仿Docker CLI,所以迁移非常顺利。

综上所述,Colima方案通过Lima启动基于vz技术的虚拟机,在macOS上使用Docker CLI与虚拟机内的dockerd交互,由dockerd调用containerd和runc控制容器;而Podman方案则使用Podman Machine基于applehv启动虚拟机,用户通过Podman Remote调用虚拟机内的Podman,后者直接调用crun。

安装上手

首先是安装Podman:

$ brew install podman

安装好以后初始化虚拟机。这会下载Fedora CoreOS镜像运行Linux。

$ podman machine init

现在就可以看到创建的虚拟机:

$ podman machine list

NAME VM TYPE CREATED LAST UP CPUS MEMORY DISK SIZE

podman-machine-default* applehv 4 days ago 2 seconds ago 7 2GiB 100GiB

然后就是启动虚拟机:

$ podman machine start

然后就可以正常使用了:

$ podman run --rm hello-world

Resolved "hello-world" as an alias (/etc/containers/registries.conf.d/000-shortnames.conf)

Trying to pull quay.io/podman/hello:latest...

Getting image source signatures

Copying blob sha256:1ff9adeff4443b503b304e7aa4c37bb90762947125f4a522b370162a7492ff47

Copying config sha256:83fc7ce1224f5ed3885f6aaec0bb001c0bbb2a308e3250d7408804a720c72a32

Writing manifest to image destination

!... Hello Podman World ...!

.--"--.

/ - - \

/ (O) (O) \

~~~| -=(,Y,)=- |

.---. /` \ |~~

~/ o o \~~~~.----. ~~

| =(X)= |~ / (O (O) \

~~~~~~~ ~| =(Y_)=- |

~~~~ ~~~| U |~~

Project: https://github.com/containers/podman

Website: https://podman.io

Desktop: https://podman-desktop.io

Documents: https://docs.podman.io

YouTube: https://youtube.com/@Podman

X/Twitter: @Podman_io

Mastodon: @Podman_io@fosstodon.org

哈哈哈哈这怎么和正版的不一样?这是什么小可爱?

不过先不用在意这些细节哈,我们继续。现在就可以使用Podman代替Docker了:

$ alias docker=podman

如果想要自动补全,可以安装docker-completion:

$ brew install docker-completion

使用完后,就可以关闭虚拟机,节约资源:

$ podman machine stop

Podman的镜像

在pull或者run的时候,需要指定镜像名字。如果使用一个简单的名字,例如podman pull mysql(这种被称为unqualified image name)。Podman会先查找Short-Name Aliasing配置:

$ podman machine ssh cat /etc/containers/registries.conf.d/000-shortnames.conf

[aliases]

...

# centos

"centos" = "quay.io/centos/centos"

# containers

"hello-world" = "quay.io/podman/hello"

# docker

...

# Ubuntu

"ubuntu" = "docker.io/library/ubuntu"

...

我们前面运行run hello-world的时候会看见小海豹,就是因为在别名里配置了"hello-world" = "quay.io/podman/hello",所以实际上运行的是quay.io/podman/hello镜像。

如果没有在别名配置里找到,Podman就会到配置的仓库里查找,默认配置的仓库就是Docker Hub(http://docker.io):

$ podman machine ssh cat /etc/containers/registries.conf.d/999-podman-machine.conf

...

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

这个行为就和Docker一样了。

如果要运行正版的hello-world怎么办呢?可以使用镜像全名(fully-qualified image):

$ podman run --rm docker.io/library/hello-world

...

Hello from Docker!

...

PS:hello-world是Docker的官方镜像,所以Podman里对应的镜像全名就是docker.io/library/hello-world,参考Normalization of docker.io references。如果是非官方的镜像,例如在Docker Hub的镜像pytorch/pytorch,对应的Podman里的全名就是docker.io/pytorch/pytorch。

搜索

还可以通过命令行方便的搜索镜像,不需要打开Docker Hub:

$ podman search mysql --filter=is-official

NAME DESCRIPTION

docker.io/library/mysql MySQL is a widely used, open-source relation...

这里会到unqualified-search-registries配置的仓库里进行搜索。

还可以查询某个镜像的tag,注意这里需要使用全名:

$ podman search docker.io/library/mysql --list-tags --limit 10000 | grep -i lts

docker.io/library/mysql lts

docker.io/library/mysql lts-oracle

docker.io/library/mysql lts-oraclelinux8

docker.io/library/mysql lts-oraclelinux9

也可以指定在某个仓库里搜索,格式是[仓库名字]/[search term]:

$ podman search quay.io/centos

NAME DESCRIPTION

...

quay.io/centos/centos The official CentOS base containers.

...

host-gateway问题

使用过程中我也遇到了一些问题。在使用Open WebUI的时候,按照文档说明运行会报错:

$ podman run -d -p 3000:8080 --add-host=host.docker.internal:host-gateway -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:main

报错信息:Error: failed to create new hosts file: unable to replace "host-gateway" of host entry "host.docker.internal:host-gateway": host containers internal IP address is empty.

看上去问题出现在--add-host=host.docker.internal:host-gateway。这个参数是什么意思呢?我查了资料,这个参数的含义如下:

在Docker环境下,host.docker.internal是一个特殊的主机名,用于解析为宿主机在容器内部的访问地址。这样容器内的应用便可以通过该地址访问宿主机提供的服务。

host-gateway则是一个特殊的关键字,用于在容器启动时自动解析为宿主机的IP地址,以便动态设置host.docker.internal的值。

然而,Podman默认已经提供了对host.docker.internal的解析,无需额外配置。所以解决方案是直接去掉 --add-host=host.docker.internal:host-gateway参数:

$ podman run -d -p 3000:8080 -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:main

Docker Compose

Docker Compose是容器化开发中常用的功能,Podman也通过external compose provider支持这一功能。external compose provider包括podman-compose和docker-compose两个选项。

一开始我想彻底摆脱Docker,所以使用podman-compose。不过在使用过程中遇到了一些问题,后来切换成docker-compose后问题就解决了。

Spring Boot Docker Compose Support可以让我们在运行测试或者本地服务时,不需要额外写代码就能自动启动容器。当我将Docker/Colima替换成Podman后,运行的时候Spring Boot Docker Compose Support就报错了:Cannot run program "docker": error=2, No such file or directory。

这是因为Java使用ProcessBuilder执行外部命令时,并不会读取Shell中的别名(alias)。解决这个问题,可以创建一个符号链接:

$ ln -s `brew --prefix`/bin/podman `brew --prefix`/bin/docker

然而继续运行时,报了另外一个错误,显示podman compose --ansi never config --format=json执行出错。

经过分析发现,podman-compose和docker-compose虽然在命令行上尽量保持一致,但在某些功能和参数实现上存在差异。例如,上述命令中--ansi never与--format=json参数在podman-compose下未能正确处理,导致兼容性问题。最终,我还是安装了docker-compose来解决该问题:

$ brew install docker-compose

清理Colima

现在可以正常使用Podman来完成功能了。如果你和我一样有“强迫症”,那你肯定想彻底删除Colima。

首先记得迁移Docker的镜像和Volume。然后删除Colima和Docker:

$ brew services stop colima

$ colima delete

$ brew uninstall docker colima qemu

PS:这里看到brew services stop colima,不得不说,Podman还有个缺点,就是不能通过brew services自动启动,期望以后会改进。

Colima使用的配置文件和pid文件,在~/.colima目录下。同时Docker的配置文件在~/.docker目录下。

删除不需要的配置文件:

$ rm -rf ~/.colima ~/.docker

PS:另外可以顺便检查下还有哪些工具是不再使用的:

$ brew leaves

既然到这里了,我们也看看Podman用了哪些文件:

~/.config/containers Podman的配置,包括和虚拟机的连接信息,例如podman-connections.json

~/.local/share/containers 虚拟机运行文件目录

这就是我从Docker/Colima迁移到Podman的经验总结。期间为了弄清各种技术细节,我把Podman官网翻了个底朝天,终于弄明白了它的优势,还理清了各概念之间的关系。整个过程充满挑战,却也别有一番乐趣。

相关推荐

怏怏不乐的读音是什么
365在线官网下载

怏怏不乐的读音是什么

📅 08-09 👁️ 764
病历中的生育史1-0-1-1是什么意思?
365在线官网下载

病历中的生育史1-0-1-1是什么意思?

📅 08-18 👁️ 9824
地球上最热的海
bet体育365怎么样

地球上最热的海

📅 09-04 👁️ 9052