LoginSignup
11
15

More than 1 year has passed since last update.

docker-composeからの脱却。podman-composeからのPod化までの道

Posted at

はじめに

Docker有償化で小規模コンテナ環境の代用をPodmanで運用できないか?という相談を受けたついでに色々さわったのでまとめました。
RHEL8以降、Dockerが非推奨になっており代わりにPodmanを使ってね!という話だったのですが、運用できないかといわれるとちょっと自信がなかったわけです。特にdocker-composeしたものってどうやったらPodmanで動くんだっけ?と今更ながら。。。
PodmanがM1に対応したのかなども踏まえて実際にdocker-composeから'play kube'でPod実行までを自分の環境でやってみました。

目次

  1. 準備
  2. podman-composeの実行
  3. Pod化と実行
  4. まとめ
  5. 参考文献

準備

最初に必要なものを集めます。まず適当なdocker-compose用のymlを探します。最初に参考にした赤帽ブログのwordpress用のファイルをこちらから拝借しました。

docker-compose.yml
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 machineが動かなかったり、設定追加が必要だったそうですが4.xからMac/Win(WSL)の対応強化されているそうです。実際得に引っかかることはなくインストール完了。

% brew install podman
% podman -v
podman version 4.1.1

次にmacOSで動かすためのLinux環境をPodman machineで準備します。

% 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 machineを起動して準備完了です。

% podman machine start
・・・
Machine "podman-machine-default" started successfully

これでPodmanが動かせる様になりました。
(※podmanコマンドが通らない場合はzshにexportでPATHを追加するのがいいですが今回は略)

podman-composeの実行

さて準備できたけど、まずはどうしようというところで、こちら参考にさせていただきました。なるほどPodman3.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になってこういうところはまだ不便をかんじます。マルチアーキテクチャ対応も快適にならないかな。

docker-compose.yml
  db:
    image: arm64v8/mysql

書き換えて再実行。今度はうまく行った様なのでcontainerを確認します。

% 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

コンテナが2つ立ち上がりました。
ついでにPod化されていればいいのですが、Podとしては動かせない模様。
まずはpodman-composeがちゃんと動くのかを調べるためにブラウザでhttp://localhost:8080へアクセス。
image.png
ちゃんとDBまで疎通とれていい感じです。元のファイルをほぼ変えないままでよかった。
podmanとpodman-composeでほぼdocker-composeと同じ事ができました。

Pod化と実行

Podmanを使うメリットの1つとしてkubernetesへの対応があり、kubernetes用のyamlファイルが生成できます。いずれkubernetesへの移行も想定したいのでこの機能を利用してyaml生成しておこうというのが今回のゴールです。
Podmanで実行しているPod(orコンテナ)を対象として生成する機能になるので、先のpodman-composeで実行した際に2つのコンテナが同一のPodに入っていれば通信関係も問題なくPod化できるはず!と踏んでいました。実際は別々のコンテナとして動いています(どうやってDB見つけてるんだろ。。)

ここで対応できそうな方法をいくつか考えました。

  1. 事前にPodを作成し、podman-composeでpodを指定する
  2. それぞれ別Podとして生成し、Podman networkを使って接続させる
  3. それぞれ別Podとして生成し、yamlを手でマージさせる

結論からいくと3番目の方法が一番簡単でした。

案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

こちらが参考になりました。
dnsを設定するためにプラグインを入れて、podを指名してあげる事でPodmanでもPod間通信ができるようになるそうです。ただ、これは少し手順が多く、ここまでやるならkubernetes上に持って行った方がいい印象です。
もともとの挙動に近しくするためにあくまでもPodで動かしたいので今回はパスしました。

案3

案3はまずwordpressとmysqlのPodを作成し、手マージしてしまいます。
まずはコンテナをそれぞれPod用yamlに生成します

% podman generate kube wordpress_wordpress_1 > kubernetes-wp.yml
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
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

それぞれのyamlをpodman play kube して単体で動くのを確認します。
問題なく動作したら以下のように合体させます。

kubernetes-hybrid.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: 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

1Podで3つのコンテナがはいってます。infraは自動ではいるのかな。
PORTSも若干怪しい。。。Webでアクセスしてみます。ブラウザでhttp://localhost:8081へアクセス。

image.png

無事に表示してDB疎通もできていました。

まとめ

Dockerで比較的単純な運用できているレベルの話であればPodmanを利用しても同じことができます。
kubernetesへの移行を検討している場合にはpodman-composeを利用して変換すれば、kubernetes/Openshiftへの移行がしやすくなるのではないかと思いました。

・podman-composeを使えば、docker-composeからPodmanへの移行は簡単
・podman-composeでマルチコンテナPodを作る時は一部編集が必要
・podmanはPodを管理することができるが、いきすぎた場合kubernetesで管理したほうがよさそう

podman-composeもoptionをうまく利用すればもう少し色々できそうなのでまた触ってみたいと思います。

参考文献

11
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
15