摆脱Docker-compose的限制,实现从Podman-compose到Pod化的过程
首先在咨询使用Podman来代替有偿Docker小型容器环境的同时,我也顺便尝试了一些东西,下面是总结:
从RHEL8开始,Docker已经被弃用,建议使用Podman!但是如果要求能否在Podman中进行运维,我有点不太确定。特别是已经使用了docker-compose的部署,如何能在Podman中运行呢?我现在才开始想起来…
考虑到Podman是否已经支持M1芯片等因素,我在自己的环境中实际尝试了将docker-compose转换为’play kube’来执行Pod的过程。
索引
-
准备
- 准备
-
- 执行 podman-compose
-
- Pod化和执行
-
- 总结
- 参考资料
准备好首先,我们将收集所需的东西。首先搜索适用于docker-compose的适当yml文件。此处我借用了最初参考的红帽博客上的wordpress文件。
version: '3.1'
services:
wordpress:
image: wordpress
restart: always
ports:
- 8080:80
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: exampleuser
WORDPRESS_DB_PASSWORD: examplepass
WORDPRESS_DB_NAME: exampledb
volumes:
- wordpress:/var/www/html
db:
image: mysql:5.7
restart: always
environment:
MYSQL_DATABASE: exampledb
MYSQL_USER: exampleuser
MYSQL_PASSWORD: examplepass
MYSQL_RANDOM_ROOT_PASSWORD: '1'
volumes:
- db:/var/lib/mysql
volumes:
wordpress:
db:
version: '3.1'
services:
wordpress:
image: wordpress
restart: always
ports:
- 8080:80
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: exampleuser
WORDPRESS_DB_PASSWORD: examplepass
WORDPRESS_DB_NAME: exampledb
volumes:
- wordpress:/var/www/html
db:
image: mysql:5.7
restart: always
environment:
MYSQL_DATABASE: exampledb
MYSQL_USER: exampleuser
MYSQL_PASSWORD: examplepass
MYSQL_RANDOM_ROOT_PASSWORD: '1'
volumes:
- db:/var/lib/mysql
volumes:
wordpress:
db:
下面是对上述内容的汉语本地化释义:
接下来是安装Podman。据说在3.x版本中,M1芯片无法运行podman机器,或者需要额外进行设置,但从4.x版本开始,它针对Mac/Win(WSL)进行了改进。实际上,并没有遇到任何问题,安装完成了。
% brew install podman
% podman -v
podman version 4.1.1
接下来,我们将使用Podman机器在macOS上准备一个Linux环境。
% podman machine init
顺利完成。似乎Fedora会更新到36版。
% ls -lh ~/.local/share/containers/podman/machine/qemu
total 8197592
-rw-r--r-- 1 toomori staff 604M 8 4 14:35 fedora-coreos-36.20220723.2.2-qemu.aarch64.qcow2.xz
-rw------- 1 toomori staff 3.2G 8 9 23:31 podman-machine-default_fedora-coreos-36.20220723.2.2-qemu.aarch64.qcow2
-rw-r--r-- 1 toomori staff 64M 8 4 14:58 podman-machine-default_ovmf_vars.fd
最后启动Podman机器,准备工作完成。
% podman machine start
・・・
Machine "podman-machine-default" started successfully
现在已经可以运行Podman了。
(*如果无法使用podman命令,请在zsh中通过export添加PATH,但本次省略)
podman-compose执行
现在准备好了,但首先要考虑怎么做,这里我参考了这个。原来从Podman 3.x开始也可以运行docker-compose嘛..。但我想要做的是摆脱docker-compose,希望用Podman来控制docker-compose的定义。所以我找到了podman-compose。
我们立即把这个也加进去吧。这次是pip。虽然有点担心是第三方制作的,但还是算了吧。
pip3 install podman-compose
这里的安装没有问题。在感激前辈们的同时执行。
podman-compose -f docker-compose.yml up -d
会显示一个类似的日志,表明将docker-compose.yml中列出的每个服务转换为podman run并执行。
...
Trying to pull docker.io/library/mysql:5.7...
Error: choosing an image from manifest list docker://mysql:5.7: no image found in manifest list for architecture arm64, variant "v8", OS linux
exit code: 125
podman start wordpress_db_1
Error: no container with name or ID "wordpress_db_1" found: no such container
exit code: 125
有点问题出现了。好像MySQL还不支持ARM。似乎是M1的问题,但我已经收到了v8和一些提示,所以我会更改一下。虽然没办法,但是切换到M1后仍然感到有些不方便。希望多架构支持能变得更加顺畅一些。
db:
image: arm64v8/mysql
重新修改并重新执行。 这次好像成功了,所以我们要确认一下容器。
% podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c431db05b0cb docker.io/library/wordpress:latest apache2-foregroun... 3 days ago Up 3 days ago 0.0.0.0:8080->80/tcp wordpress_wordpress_1
f24872732c1f docker.io/arm64v8/mysql:latest mysqld 3 days ago Up 3 days ago wordpress_db_1
% podman pod ps
POD ID NAME STATUS CREATED INFRA ID # OF CONTAINERS

将Pod转化并执行使用Podman的优点之一是可以支持Kubernetes,并且可以生成用于Kubernetes的yaml文件。我们希望考虑将来迁移到Kubernetes,所以这次的目标是利用这个功能来生成yaml文件。
这个功能是针对正在使用Podman运行的Pod(或容器)生成的,所以我们认为,如果在之前使用podman-compose时,两个容器都在同一个Pod中,那么通信关系也应该可以顺利地转化为Pod!但实际上,它们是作为独立的容器运行的(不知道它是如何找到数据库的…)。
我在这里考虑了一些可能可行的方法。
-
- 事前に创建Pod,并使用podman-compose指定Pod。
-
- 将它们分别生成为不同的Pod,并使用Podman网络进行连接。
- 将它们分别生成为不同的Pod,并手动合并YAML文件。
根据结论,第三种方法最简单。
请使用母语中文转述以下内容,只需提供一种选项:案1
在podman-run-args参数中使用–pod来指定pod并尝试。
% podman pod create --name wp-pod
56977b21b4ce8062bbbc3eac4c013feb39d98bb10d4ed9f61fc50a93d44a9ee0
% podman pod ps
POD ID NAME STATUS CREATED INFRA ID # OF CONTAINERS
56977b21b4ce wp-pod Created 3 days ago 7b8bf8e908ee 1
% podman-compose -f docker-compose.yml up -d --podman-run-args="--pod='wp-pod'"
...
podman-compose: error: unrecognized arguments: --podman-run-args=--pod='wp-pod'
如果选项出了问题或者没能成功执行,请告诉我该如何解决。
2号案这是一个有用的参考。据说,通过安装插件并指定Pod,您可以在Podman上实现Pod之间的通信。但是,这个过程稍微繁琐,如果要做到这一点,最好将其移到Kubernetes上执行。由于我想尽量保持与原始行为的相似性,所以这次我选择了pass。
第三个案例
首先,案例3将创建WordPress和MySQL的Pod,并手动合并它们。
首先,我们将生成各自的容器,并将其合并到用于Pod的yaml文件中。
% podman generate kube wordpress_wordpress_1 > kubernetes-wp.yml
# Save the output of this file and use kubectl create -f to import
# it into Kubernetes.
#
# Created with podman-4.1.1
# NOTE: If you generated this yaml from an unprivileged and rootless podman container on an SELinux
# enabled system, check the podman generate kube man page for steps to follow to ensure that your pod/container
# has the right permissions to access the volumes added.
---
apiVersion: v1
kind: Pod
metadata:
annotations:
io.kubernetes.cri-o.TTY/wordpresswordpress1: "false"
io.podman.annotations.autoremove/wordpresswordpress1: "FALSE"
io.podman.annotations.init/wordpresswordpress1: "FALSE"
io.podman.annotations.privileged/wordpresswordpress1: "FALSE"
io.podman.annotations.publish-all/wordpresswordpress1: "FALSE"
creationTimestamp: "2022-08-05T13:46:41Z"
labels:
app: wordpresswordpress1-pod
name: wordpresswordpress1-pod
spec:
containers:
- args:
- apache2-foreground
env:
- name: WORDPRESS_DB_USER
value: exampleuser
- name: WORDPRESS_DB_PASSWORD
value: examplepass
- name: WORDPRESS_DB_NAME
value: exampledb
- name: WORDPRESS_DB_HOST
value: wordpressdb1-pod
image: docker.io/library/wordpress:latest
name: wordpresswordpress1
ports:
- containerPort: 80
hostPort: 8081
securityContext:
capabilities:
drop:
- CAP_MKNOD
- CAP_NET_RAW
- CAP_AUDIT_WRITE
volumeMounts:
- mountPath: /var/www/html
name: wordpress_wordpress-pvc
volumes:
- name: wordpress_wordpress-pvc
persistentVolumeClaim:
claimName: wordpress_wordpress
% podman generate kube wordpress_db_1 > kubernetes-mysql.yml
# Created with podman-4.1.1
# NOTE: If you generated this yaml from an unprivileged and rootless podman container on an SELinux
# enabled system, check the podman generate kube man page for steps to follow to ensure that your pod/container
# has the right permissions to access the volumes added.
---
apiVersion: v1
kind: Pod
metadata:
annotations:
io.kubernetes.cri-o.TTY/wordpressdb1: "false"
io.podman.annotations.autoremove/wordpressdb1: "FALSE"
io.podman.annotations.init/wordpressdb1: "FALSE"
io.podman.annotations.privileged/wordpressdb1: "FALSE"
io.podman.annotations.publish-all/wordpressdb1: "FALSE"
creationTimestamp: "2022-08-05T09:32:54Z"
labels:
app: wordpressdb1-pod
name: wordpressdb1-pod
spec:
containers:
- args:
- mysqld
env:
- name: MYSQL_PASSWORD
value: examplepass
- name: MYSQL_RANDOM_ROOT_PASSWORD
value: "1"
- name: MYSQL_USER
value: exampleuser
- name: MYSQL_DATABASE
value: exampledb
image: docker.io/arm64v8/mysql:latest
name: wordpressdb1
securityContext:
capabilities:
drop:
- CAP_MKNOD
- CAP_NET_RAW
- CAP_AUDIT_WRITE
volumeMounts:
- mountPath: /var/lib/mysql
name: wordpress_db-pvc
volumes:
- name: wordpress_db-pvc
persistentVolumeClaim:
claimName: wordpress_db
首先,案例3将创建WordPress和MySQL的Pod,并手动合并它们。
首先,我们将生成各自的容器,并将其合并到用于Pod的yaml文件中。
% podman generate kube wordpress_wordpress_1 > kubernetes-wp.yml
# Save the output of this file and use kubectl create -f to import
# it into Kubernetes.
#
# Created with podman-4.1.1
# NOTE: If you generated this yaml from an unprivileged and rootless podman container on an SELinux
# enabled system, check the podman generate kube man page for steps to follow to ensure that your pod/container
# has the right permissions to access the volumes added.
---
apiVersion: v1
kind: Pod
metadata:
annotations:
io.kubernetes.cri-o.TTY/wordpresswordpress1: "false"
io.podman.annotations.autoremove/wordpresswordpress1: "FALSE"
io.podman.annotations.init/wordpresswordpress1: "FALSE"
io.podman.annotations.privileged/wordpresswordpress1: "FALSE"
io.podman.annotations.publish-all/wordpresswordpress1: "FALSE"
creationTimestamp: "2022-08-05T13:46:41Z"
labels:
app: wordpresswordpress1-pod
name: wordpresswordpress1-pod
spec:
containers:
- args:
- apache2-foreground
env:
- name: WORDPRESS_DB_USER
value: exampleuser
- name: WORDPRESS_DB_PASSWORD
value: examplepass
- name: WORDPRESS_DB_NAME
value: exampledb
- name: WORDPRESS_DB_HOST
value: wordpressdb1-pod
image: docker.io/library/wordpress:latest
name: wordpresswordpress1
ports:
- containerPort: 80
hostPort: 8081
securityContext:
capabilities:
drop:
- CAP_MKNOD
- CAP_NET_RAW
- CAP_AUDIT_WRITE
volumeMounts:
- mountPath: /var/www/html
name: wordpress_wordpress-pvc
volumes:
- name: wordpress_wordpress-pvc
persistentVolumeClaim:
claimName: wordpress_wordpress
% podman generate kube wordpress_db_1 > kubernetes-mysql.yml
# Created with podman-4.1.1
# NOTE: If you generated this yaml from an unprivileged and rootless podman container on an SELinux
# enabled system, check the podman generate kube man page for steps to follow to ensure that your pod/container
# has the right permissions to access the volumes added.
---
apiVersion: v1
kind: Pod
metadata:
annotations:
io.kubernetes.cri-o.TTY/wordpressdb1: "false"
io.podman.annotations.autoremove/wordpressdb1: "FALSE"
io.podman.annotations.init/wordpressdb1: "FALSE"
io.podman.annotations.privileged/wordpressdb1: "FALSE"
io.podman.annotations.publish-all/wordpressdb1: "FALSE"
creationTimestamp: "2022-08-05T09:32:54Z"
labels:
app: wordpressdb1-pod
name: wordpressdb1-pod
spec:
containers:
- args:
- mysqld
env:
- name: MYSQL_PASSWORD
value: examplepass
- name: MYSQL_RANDOM_ROOT_PASSWORD
value: "1"
- name: MYSQL_USER
value: exampleuser
- name: MYSQL_DATABASE
value: exampledb
image: docker.io/arm64v8/mysql:latest
name: wordpressdb1
securityContext:
capabilities:
drop:
- CAP_MKNOD
- CAP_NET_RAW
- CAP_AUDIT_WRITE
volumeMounts:
- mountPath: /var/lib/mysql
name: wordpress_db-pvc
volumes:
- name: wordpress_db-pvc
persistentVolumeClaim:
claimName: wordpress_db
请使用podman play kube命令逐个验证每个YAML文件是否能够独立运行。
如果运行正常,然后将它们合并如下。
# Save the output of this file and use kubectl create -f to import
# it into Kubernetes.
#
# Created with podman-4.1.1
# NOTE: If you generated this yaml from an unprivileged and rootless podman container on an SELinux
# enabled system, check the podman generate kube man page for steps to follow to ensure that your pod/container
# has the right permissions to access the volumes added.
---
apiVersion: v1
kind: Pod
metadata:
annotations:
io.kubernetes.cri-o.TTY/wordpresswordpress1: "false"
io.podman.annotations.autoremove/wordpresswordpress1: "FALSE"
io.podman.annotations.init/wordpresswordpress1: "FALSE"
io.podman.annotations.privileged/wordpresswordpress1: "FALSE"
io.podman.annotations.publish-all/wordpresswordpress1: "FALSE"
creationTimestamp: "2022-08-05T13:46:41Z"
labels:
app: wordpresswordpress1-pod
name: wordpresswordpress1-pod
spec:
containers:
- args:
- apache2-foreground
env:
- name: WORDPRESS_DB_USER
value: exampleuser
- name: WORDPRESS_DB_PASSWORD
value: examplepass
- name: WORDPRESS_DB_NAME
value: exampledb
- name: WORDPRESS_DB_HOST
value: 127.0.0.1
image: docker.io/library/wordpress:latest
name: wordpresswordpress1
ports:
- containerPort: 80
hostPort: 8081
securityContext:
capabilities:
drop:
- CAP_MKNOD
- CAP_NET_RAW
- CAP_AUDIT_WRITE
volumeMounts:
- mountPath: /var/www/html
name: wordpress_wordpress-pvc
- args:
- mysqld
env:
- name: MYSQL_PASSWORD
value: examplepass
- name: MYSQL_RANDOM_ROOT_PASSWORD
value: "1"
- name: MYSQL_USER
value: exampleuser
- name: MYSQL_DATABASE
- value: exampledb
image: docker.io/arm64v8/mysql:latest
name: wordpressdb1
securityContext:
capabilities:
drop:
- CAP_MKNOD
- CAP_NET_RAW
- CAP_AUDIT_WRITE
volumeMounts:
- mountPath: /var/lib/mysql
name: wordpress_db-pvc
volumes:
- name: wordpress_wordpress-pvc
persistentVolumeClaim:
claimName: wordpress_wordpress
- name: wordpress_db-pvc
persistentVolumeClaim:
claimName: wordpress_db
我只改变了WORDPRESS_DB_HOST的值。将其修改为指向127.0.0.1。
(*为了方便起见,我将8080改为了8081。)
其他只需对行进行重新排序即可。
- name: WORDPRESS_DB_HOST
value: 127.0.0.1
由于Pod化已经完成,所以使用podman play kube来执行。
% podman play kube kubernetes-hybrid.yml
确认动作
% podman pod ps
POD ID NAME STATUS CREATED INFRA ID # OF CONTAINERS
f6ee088f1f1f wordpresswordpress1-pod Running 3 days ago 6ff1c5d2686a 3
% podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6ff1c5d2686a localhost/podman-pause:4.1.1-1655914710 3 days ago Up 3 days ago 0.0.0.0:8081->80/tcp f6ee088f1f1f-infra
72e336da5e7b docker.io/library/wordpress:latest apache2-foregroun... 3 days ago Up 3 days ago 0.0.0.0:8081->80/tcp wordpresswordpress1-pod-wordpresswordpress1
1d36ae3682ed docker.io/arm64v8/mysql:latest mysqld 3 days ago Up 3 days ago 0.0.0.0:8081->80/tcp wordpresswordpress1-pod-wordpressdb1
我有一个Pod,里面有三个容器。infra是否会自动进入呢?PORTS也有点可疑…我会尝试通过Web访问。在浏览器中输入http://localhost:8081进行访问。

顺利显示并成功进行了与数据库的通信。
概述如果是关于使用相对简单操作的层次的话,使用Podman也可以完成同样的事情。如果考虑迁移到Kubernetes,使用podman-compose进行转换可能会使迁移到Kubernetes/Openshift更加容易,我认为。
使用podman-compose,从docker-compose迁移到Podman很简单。
在使用podman-compose创建多容器Pod时,需要进行部分编辑。
虽然podman可以管理Pod,但如果情况过于复杂,还是建议使用kubernetes进行管理。
如果我能巧妙地利用podman-compose的选项,可能还能做更多不同的事情,所以我想再次尝试一下。
文献引用
-
赤帽エンジニアブログ Podman v3 で docker-composeを実行する
- 赤帽エンジニアブログ Podman v3 で docker-composeを実行する
-
- 豆蔵デベロッパーサイト macOS 上で Podman を動かす
-
- Podman で Compose したかったらどうするの?
- ZU-MIN.COM podman のコンテナ名で通信する