FedoraでPodman Composeを使う:rootlessマルチコンテナ管理のためのDocker Compose代替ガイド

Fedora tutorial - IT technology blog
Fedora tutorial - IT technology blog

複数コンテナの連携が必要になったときの問題

podman runで単一コンテナを動かすのは簡単だ。しかし、アプリがwebアプリ、データベース、キャッシュ、リバースプロキシの3〜4コンテナを連携して動かす必要があると、話は変わってくる。ネットワークは手動で作る必要があり、起動順序も正確に管理しなければならない。環境変数は正しい場所に渡し、ボリュームも同期してマウントする必要がある。最初のデプロイはなんとかなる。しかし2回目、あるいは別のマシンに移行するとなると、半日仕事になる。

私はFedoraをメインの開発マシンとして2年間使っている。パッケージの更新速度には満足しており、Podmanは他のディストロより数ヶ月先を走っていることが多い。ただ、FedoraがDockerの代わりにPodmanを推進しているからこそ、多くの人が現実的な疑問に直面する。古いdocker-compose.ymlファイルはどうやって動かせばいいのか?

Fedoraで複数コンテナをオーケストレーションする4つの方法

方法1:Docker Composeをそのまま使う

FedoraにDocker Engineをインストールすることは可能で、誰も止めない。Docker Composeも問題なく動き、composeファイルを変更する必要もない。

ただし、いくつか不便な点がある。Docker daemonはrootで動かす必要があり、別途systemdサービスも管理しなければならない。また、FedoraはDockerを公式リポジトリに含めなくなったため、Fedoraのバージョンを上げるたびに別途Dockerリポジトリを確認する必要がある。私はFedora 38から39へのアップグレード後にcgroup v2の競合が原因でDocker daemonがクラッシュした経験があり、原因の特定に2時間近くかかった。

方法2:Podman Pods — ネイティブだが冗長

Podmanは「pod」という概念をサポートしている。これはネットワーク名前空間を共有するコンテナグループで、Kubernetes podに似ている。podを作成してからコンテナを追加する:

podman pod create --name myapp -p 8080:80
podman run -d --pod myapp nginx
podman run -d --pod myapp postgres:15

問題は、バージョン管理できる設定ファイルが存在しないことだ。スタックを再作成するには、すべてのコマンドを最初から入力し直す必要がある。docker-compose.ymlのような宣言型ワークフローに慣れている場合、この方法は後退しているように感じるだろう。

方法3:Quadlet — プロダクション向けsystemdネイティブ

Podman 4.4+(Fedora 38+)以降、Quadletを使えば~/.config/containers/systemd/.container.podファイルを書くだけで、systemdが自動的にunitファイルを生成してくれる。プロダクション環境に適しており、journalctlとの統合も優れ、再起動ポリシーも充実している。

しかし、Quadletを使いこなすにはdocker-compose.ymlとはまったく異なる新しい構文を一から学ぶ必要がある。10〜15のプロジェクトがcomposeファイルを使っている場合、すべてをQuadletに移行するのは一筋縄ではいかない。

方法4:Podman Compose — 現実的なバランスポイント

Podman ComposeはDockerの代わりにPodmanバックエンドを使ってdocker-compose.ymlファイルを実行するPythonツールだ。root daemonは不要で、完全なrootlessをサポートし、Docker Composeと同じ構文を維持している。

4つのアプローチの比較

アプローチ Rootless composeファイル互換性 Systemd統合 学習曲線
Docker Compose ❌ Root daemon ✅ 100% 手動
Podman Pods ❌ 構文が異なる 手動
Quadlet ❌ 移行が必要 ✅ Native
Podman Compose ✅ ~90% ラップ可能

Podman Composeは仕様を100%サポートしているわけではない。extendsや複雑なprofiles、一部のdeployオプションなどが欠けている場合がある。しかし、一般的なユースケースの90%においては、修正なしでそのまま動作する。

FedoraへのPodman Composeのインストール

FedoraはFedora 36+から公式リポジトリにPodman Composeを収録している:

sudo dnf install podman-compose
podman-compose --version

PyPIから最新版を使いたい場合:

pip install --user podman-compose

実践デプロイ:Web app + PostgreSQL + Redis

プロジェクト構造の作成

mkdir ~/myapp && cd ~/myapp
mkdir -p app nginx/conf.d

docker-compose.ymlを書く

version: '3.8'

services:
  web:
    image: python:3.11-slim
    working_dir: /app
    volumes:
      - ./app:/app:Z
    command: python -m http.server 8000
    depends_on:
      - db
      - cache
    environment:
      - DATABASE_URL=postgresql://user:password@db:5432/mydb
      - REDIS_URL=redis://cache:6379

  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
      POSTGRES_DB: mydb
    volumes:
      - pgdata:/var/lib/postgresql/data

  cache:
    image: redis:7-alpine
    command: redis-server --save 60 1

  nginx:
    image: nginx:alpine
    ports:
      - "8080:80"
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d:ro
    depends_on:
      - web

volumes:
  pgdata:

nginxの設定ファイル

# nginx/conf.d/default.conf
server {
    listen 80;
    location / {
        proxy_pass http://web:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

基本コマンド

# スタック全体を起動する
podman-compose up -d

# リアルタイムでログを確認する
podman-compose logs -f

# 状態を確認する
podman-compose ps

# コンテナを停止・削除する(ボリュームは保持)
podman-compose down

# ボリュームデータごと停止・削除する
podman-compose down -v

Fedoraでrootless実行時につまずきやすいポイント

ボリュームマウントとSELinux

FedoraはデフォルトでSELinuxをenforcingモードで実行している。ホストディレクトリをコンテナにマウントする際は、:Zラベル(このコンテナ専用にrelabel)または:zラベル(複数コンテナで共有)を追加する必要がある:

volumes:
  - ./app:/app:Z          # このコンテナ専用にrelabel
  - ./config:/etc/app:z   # 共有 — 複数コンテナが読み取り可能

このラベルの付け忘れは、FedoraでPodmanを実行する際に「Permission denied」エラーが発生する最大の原因だ。コンテナは正常に起動し、ログもきれいに見えるが、内部のアプリがファイル読み取りエラーを報告し続ける。SELinuxがバックグラウンドでブロックしているにもかかわらず、明確なログが一切出ないのだ。

1024番未満のポートを使う場合

rootlessコンテナはデフォルトで1024未満のポートにバインドできない。開発環境では高いポート番号を使えば十分だ。どうしてもポート80/443が必要な場合:

# 一般ユーザーのポート制限を下げる(rootで一度だけ実行)
echo "net.ipv4.ip_unprivileged_port_start=80" | sudo tee /etc/sysctl.d/99-podman-ports.conf
sudo sysctl --system

再起動時の自動起動

Podman ComposeにはQuadletのようなsystemd統合機能が組み込まれていないが、ユーザーサービスでラップすることができる:

mkdir -p ~/.config/systemd/user

cat > ~/.config/systemd/user/myapp.service << 'EOF'
[Unit]
Description=My App Stack
After=default.target

[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=%h/myapp
ExecStart=/usr/bin/podman-compose up -d
ExecStop=/usr/bin/podman-compose down
TimeoutStartSec=0

[Install]
WantedBy=default.target
EOF

systemctl --user enable --now myapp.service

# ユーザーがログインしていない場合でもサービスを実行する
loginctl enable-linger $USER

Quadletに移行すべきタイミング

Podman ComposeはdevelopmentとstagingEnvironmentに適している。一方、Fedora Serverのproduction環境ではどうだろうか?Quadletはまったく別の話だ。ログはsystemd journalに直接入り、依存関係管理はunit fileで行い、外部のラッパースクリプトなしで自動再起動できる。

朗報は、Fedora 40以降、podletというツールがcomposeファイルをQuadletへ自動変換してくれることだ:

sudo dnf install podlet
podlet compose docker-compose.yml

.container.networkファイルをそのまま使える状態で生成してくれるため、ゼロから書き直すことなく移行できる。

まとめ

Fedoraの開発環境においては、Podman Composeが最も合理的な出発点だ。rootlessでdaemon不要、既存のcomposeファイルの90%をそのまま動かせる。プロジェクトが成長してproductionレベルの安定性——適切な再起動ポリシー、journald、依存関係グラフ——が必要になったとき、初めてQuadletへの投資が価値を持つ。そのときはpodletが変換を担当してくれるため、出力を確認するだけで移行が完了する。

Share: