😟

Docker ComposeからPodmanに移行する

2025/01/25に公開

環境

  • OS: CentOS Stream 10

  • 移行元: Docker + Docker Compose

  • 移行元: Podman(ユーザー権限) + Podman Compose

サードパーティーのものがDocker Composeしか提供されていない時に「docker-compose.yml」のままPodmanで動かせないかなと思って試行錯誤。

自作のものはKubernetes YAMLに書き直せばよいものの、配布されているものはいつ変わるかわからないので出来るだけそのまま動かしたかった。

動かす

Podmanのインストール

これはCentOS Stream 10に標準で入っていた。

Podmanの有効化

デーモンレスなのでコマンドをたたけば動くみたいだが、Cockpit上で「Podmanコンテナー」が表示された方が気持ちいい。

systemctl --user enable --now podman.socket

ユーザー権限でpodman.socketサービスを立ち上げれば見られるようになる。

podman-composeのインストール

標準だとpythonは入っているがpipが入っていないので、追加でインストールする。

sudo dnf install python3-pip

その後、podman-composeをインストールする。

pip3 install podman-compose

podman-composeでPodの実行

docker-compose.ymlが保存されているディレクトリ上で

podman-compose up

で普通に立ち上がる(はずだった。)

トラブルシューティング

[.env]の中身が参照されない

うまく動かないので以下のコマンドで認識されたconfigファイルを確認する

podman-compose config

.envに書いた環境変数COMPOSE_FILEが参照されていない。
podman-composeのソースコードを見たらYAMLの読み込み後に.envを読み込んでいるので、これだと動かない。

-fパラメータを使うか

podman-compose -f docker-compose.yml -f docker-compose.production.yml up

環境変数に入れるしかない。

COMPOSE_FILE=docker-compose.yml:docker-compose.production.yml podman-compose up

.bash_profileに書くか迷ったけど、結局実行用のスクリプトファイルを用意することにした。
う~ん、だったらもうCOMPOSE_FILE環境変数なんて要らないじゃないか。

PC再起動時に自動起動されない

docker-compose.ymlにはrestart: alwaysと記載してあるが、再起動しても起動しなかった。

systemctl --user enable podman-restart

podman-restartサービスを有効にすることで、ログイン後に自動起動させることはできたが、OS起動のあとに勝手にコンテナも立ち上がってほしい。

loginctl enable-linger ユーザー名

ログインしていない状態(起動直後やログアウトしているとき)でもユーザー権限のサービスを動作させるよう、systemdにユーザー名を登録する。
これでコンテナを自動起動させようとすることはできたが、podman-restartが以下のエラーで停止している。

pasta[1364]: External interface not usable
podman[1280]: Error: unable to start container "(コンテナID)" setting up Pasta: pasta failed with exit code 1:
podman[1280]: External interface not usable
systemd[1047]: podman-restart.service: Main process exited, code=exited, status=125/n/a
systemd[1047]: podman-restart.service: Failed with result 'exit-code'.

pastaってなんだろうなと思ったら、Podmanが依存するネットワーク関係のパッケージの模様。
ネットワーク機能が利用できる前に立ち上がるためエラーが起きているようだ。

通常であればnetwork.targetを待機するように記述すればよいのだが(というかすでにpodman-restart.serviceへ書いてある)、ユーザーユニットはシステムユニットを待機できない模様。
なんだそれやる気あんのか。

ということで

  • podman-restart.serviceを編集しない
  • docker-compose.ymlを維持してそのまま流用(ユニットファイルを作らない)
  • コンピューターの起動に合わせてコンテナを自動起動
  • Podmanをユーザー権限で動かす

という条件を満たす方法は2025年1月時点ではないようです。動いていたDockerの環境返してくれ

なので苦渋の決断として podman-restart.serviceファイルを編集して待機先を変えてあげることにした。

先ほどのリンク(GitHubのIssue)に出てきているような回避策はすでに
/usr/lib/systemd/user/podman-user-wait-network-online.service
へインストールされていたので、それを待つよう変えるだけで良い。
/usr/lib/systemd/user/podman-restart.serviceの中身を以下へ。

[Unit]
Description=Podman Start All Containers With Restart Policy Set To Always
Documentation=man:podman-start(1)
StartLimitIntervalSec=0
Wants=podman-user-wait-network-online.service
After=podman-user-wait-network-online.service

変えてあるのはWantsAfterのところ。
この状態でOSを再起動したらちゃんとコンテナが立ち上がってくれた。

う~ん、忘れたころにこのファイルがもとに戻っていて動かなくなりそう。

試してないけどpodman-composeにこだわらなければ以下の手段で回避できそう。

podman generate systemd ~
で作ったユニットファイルまたはQuadletに読み込ませるユニットファイルに

After=podman-user-wait-network-online.service
Wants=podman-user-wait-network-online.service

を記載してあげれば動きそう。誰か公式のドキュメントに書いてくれていてもいいじゃない。

終わりに

podman-composeを頼りにするくらいなら、公式ドキュメントも整備されているしDockerのほうが無難な気がする。
今回の出鼻をくじかれた経験から思うに

docker-compose.ymlがそのまま使えるし互換性がある

とはいかない。

Discussion