2 ポイント 投稿者 GN⁺ 2025-03-25 | 1件のコメント | WhatsAppで共有
  • Podmanはデーモンを持たないため、サーバー起動後にコンテナを安定して立ち上げる実行主体が必要であり、Quadlet はこれをsystemdサービスファイル方式で解決する
  • 従来の podman generate systemd ではコンテナ作成とサービスファイル生成を別々に処理する必要があり、生成ファイルを変更するたびに 手動編集 の負担が生じていた
  • Quadletは ~/.config/containers/systemd.container ファイルに [Container], [Service], [Install] の設定をまとめて置き、Podmanオプションとsystemdの動作を一か所で管理する
  • rootless Podmanでは起動時の自動開始のために WantedBy=default.targetlingerの有効化 が必要で、multi-user.target はユーザーモードでは定義されていない
  • AutoUpdate=registry、systemdの依存関係、ディレクトリごとのファイル整理、podlet 変換ツールまで活用すれば、Quadletは rootless・daemonless なPodman運用に適している

なぜQuadletが必要なのか

  • Quadlet はPodmanコンテナをsystemdサービスのように実行できるようにする仕組み
    • コンテナをバックグラウンドで実行できる
    • サーバー再起動後にコンテナを自動起動できる
  • Podmanコンテナをsystemd配下で実行する方法自体は新しくない
    • 従来は podman generate systemd コマンドを使っていた
    • このコマンドは現在、Quadletへ移行するよう 非推奨の警告 を表示する
  • Podmanはdaemonlessな構造のため、デーモンなしでコンテナを起動してくれる実行主体が必要になる

従来の podman generate systemd 方式の不便さ

  • 従来の方法では、まず podman create でコンテナを作成する必要があった
    • 例のコンテナでは docker.io/library/postgres:16 イメージを使用する
    • -p 5432:5432、ボリュームマウント、POSTGRES_PASSWORD 環境変数、io.containers.autoupdate=registry ラベルを含める
  • その後 podman generate systemd test-db -fn --new を実行して container-test-db.service ファイルを生成していた
  • 生成されたサービスファイルは ~/.config/systemd/user に配置し、次のコマンドで有効化・起動していた
    • systemctl --user enable --now container-test-db
  • この流れでは、コンテナ作成、サービスファイル生成、必要に応じたファイル移動、サービス有効化を繰り返すことになる
  • コンテナ作成コマンドが長くなると、後で再実行するために シェルスクリプト を別途管理しなければならなかった
  • 生成されたsystemdサービスファイルをカスタマイズするには、毎回あらためて 手動修正 が必要だった

Quadletファイルの構成

  • Quadlet方式では ~/.config/containers/systemd ディレクトリを作成し、その中に .container ファイルを置く
  • 例の test-db.container ファイルには次の要素が含まれる
    • [Container]
      • Image=docker.io/library/postgres:16
      • AutoUpdate=registry
      • PublishPort=5432:5432
      • Volume=%h/volumes/test-db:/var/lib/postgresql/data:Z
      • Environment=POSTGRES_PASSWORD=CHANGE_ME
    • [Service]
      • Restart=always
    • [Install]
      • WantedBy=default.target
  • .container ファイルは通常のsystemdサービスファイルだが、特別な [Container] セクションを含む
  • [Container] の多くのオプションは podman create で使うコマンドラインオプションに対応している
    • Image: 使用するイメージとタグ
    • AutoUpdate=registry: --label "io.containers.autoupdate=registry" に対応
    • PublishPort: -p に対応
    • Volume: -v に対応
    • Environment: -e に対応
  • ユーザーのホームディレクトリでは ~ の代わりにsystemd指定子の %h を使う必要がある
  • [Service]Restart=always は、手動で停止しない限りコンテナを常に再起動させる
  • [Install]WantedBy=default.target は、コンテナを起動時に自動開始させる

rootless Podmanで必要なsystemd設定

  • rootlessコンテナでは multi-user.target ではなく default.target を使う必要がある
    • multi-user.target はsystemdユーザーモードでは定義されていない
    • systemctl --user status multi-user.target で確認できる
    • システムモードでは systemctl status multi-user.target で確認可能
  • systemdユーザーサービスとしてコンテナを実行するため、ユーザーがログインしていなくてもコンテナが起動するようにするにはlingerを有効化する必要がある
    • loginctl enable-linger
  • サーバー再起動後の自動起動が必要なら、lingerの有効化は必須
  • 新しいサービスファイルをsystemdに認識させるには、次のコマンドを実行する
    • systemctl --user daemon-reload
  • コンテナの起動と状態確認は、systemdとPodmanの両方から行える
    • systemctl --user start test-db
    • systemctl --user status test-db
    • podman ps
  • デフォルトのコンテナ名は、サービスファイル名の前に systemd- が付いた形になる
    • test-db.container のデフォルトのコンテナ名は systemd-test-db
    • 衝突を避けるための命名規則
    • [Container] セクションの ContainerName オプションで明示的に指定することもできる

Quadletの運用上の利点

  • Quadletはコンテナサービス設定を1つのファイルで管理できるようにする
    • 従来方式のように、サービスファイルを生成するスクリプトと生成済みサービスファイルを別々に管理する必要がない
  • systemdの [Unit][Service] セクションで使えるオプションを利用できる
    • たとえばコンテナ起動前に実行するコマンドを StartExecPre で指定できる
    • 生成されたファイルを後から手動で修正する工程が減る
  • シェルスクリプトを書いてデバッグする代わりに、設定ファイル 中心でコンテナを運用できる
  • コンテナ間の 依存関係 をsystemd方式で表現しやすい

コンテナ間の依存関係の表現

  • アプリコンテナがデータベースコンテナに依存するなら、systemdの [Unit] セクションで関係を指定できる
  • OxiTraffic コンテナは test-db コンテナに依存する例
    • [Unit]Requires=test-db.service を設定し、データベースが起動するときだけアプリが起動するようにする
    • After=test-db.service を設定し、2つのコンテナが並列に起動しないようにする
  • 参照時には .container ファイル名ではなく サービス名 を使う
    • test-db.container: ファイル名
    • test-db.service: サービス名
    • systemd-test-db: デフォルトのコンテナ名
  • アプリがデータベースと通信するには、両方のコンテナの [Container] セクションに Network オプションを追加する必要があるが、ネットワーク設定はここでは扱わない

複数ファイルとグループ化

  • Quadletはコンテナごとに別々の .container ファイルを置く構成にできる
  • マルチコンテナアプリを1つのDocker Composeファイルにすべて入れる方式より、コンテナごとのファイルのほうが 認知負荷 を下げられる場合がある
  • Docker Composeファイルが数百行・数十コンテナを含むと、保守が難しくなりがち
  • Docker Composeにも複数ファイルへ分割する機能はある
  • Quadletでは ~/.config/containers/systemd 内のディレクトリにunitファイルを置ける
    • 例では oxitraffic ディレクトリを作成し、アプリとデータベースのファイルを一緒に置ける

イメージ更新

  • AutoUpdate=registry を設定すると、podman auto-update でイメージ更新を確認できる
  • レジストリに使用中のタグと互換性のある新しいイメージがあれば、Podmanがイメージをpullしてコンテナを再起動する
  • Dockerではこの用途に Watchtower のようなツールが必要になることがあるが、Podmanはこの機能を標準で備えている
  • latest のようなタグは危険な場合がある
    • OxiTrafficで latest を使うと、次のバージョンのbreaking changeを含む可能性がある
    • PostgreSQLで latest を使うと、新しいメジャーバージョンへ上がる可能性があり、PostgreSQLのメジャーアップグレードには常に手動マイグレーションが必要
  • 本番運用では、breaking changeにつながらないタグを使うべき
  • podman auto-update を数日ごとに手動実行して、何が更新されたかを確認し、その後コンテナが正常かどうかを確認する運用も可能

podman-compose と移行ツール

  • podman-compose はComposeファイルをPodmanで実行するPythonスクリプト
  • 長期的なDocker Compose代替として見づらい理由は次のとおり
    • Compose仕様とPodman・systemdの間の翻訳レイヤーであり、systemdのすべての機能を使えるようにはしない
    • 公式PodmanプロジェクトはRustやGoのようなコンパイル言語で書かれている
    • 最終コミットが5か月前で、活発に保守されていない
  • QuadletはPodmanの rootless・daemonless な設計とより相性がよい
  • ComposeファイルからQuadletを試すなら podlet を使える
    • PodmanコマンドやDocker ComposeファイルからQuadletファイルを生成できるRust製ツール

さらに読む資料

1件のコメント

 
GN⁺ 2025-03-25
Hacker News の意見
  • Quadlet は Podman から出てきたものの中でも最高に近く、Podman に興味がある人やコンテナベースのワークロードへ移行しようとしている人に強くおすすめする
    コンテナを通常のシステムサービスのように組み込んで扱え、一緒に動かすために別途オーケストレーション層を学んだり、非コンテナのリソースに依存したりする必要がない
    既存の systemd ユニット をそのまま書けばよく、自動更新や失敗時のサービス再起動/通知はおまけとして付いてくる
    Docker で似たことをしようとするやり方では、巨大な run コマンドで Docker デーモンを迂回した結果、幽霊のようなサービスやコンテナが残ることが多かったが、Quadlet ははるかにすっきりしていて、設定も /etc/systemd/.config/systemd/usr/local/lib/systemd のような systemd ユニットの場所にまとまっているのでバックアップしやすい
    ただしローカル開発における docker-compose の答えではなく、Podman チームもその領域にはあまり関心がないように見える
    ユーザーコンテナは、バックグラウンドデータベースのような長時間実行するローカルテストインフラには向いているが、一般的な「コンパイル → docker compose up → テスト → docker compose down」のループには手間がかかりすぎる
    現実的な答えは .kube Quadlet(Kubernetes play)か、Podman ソケットに対して docker compose を使うことだ
    ここ数か月、余暇に Quadlet を管理する GitOps ツールを作るほど気に入っており、コンテナ化されたサーバーを管理する正しいやり方のように感じている
    [0] が podman-compose ではない点が重要だ。記事でも podman-compose はいまひとつで、開発が不足していると指摘している。Podman は compose 仕様の大半を実装しているので、ほとんどの状況で docker compose を使える
    RH が最初に Podman を推し始めたときに試した人たちは、Podman 3 の中途半端さと podman-compose の悪い体験のせいで離れてしまった可能性が高い

    • RH 流に近づけたくて Quadlet と podlet を試そうとしたが、Podman 上の docker compose から移行した体験はひどいものだった
      いくつものフラグを変え、バージョンを上げ、podlet 自体が別のツールへ乗り換えるよう勧める流れに従っているうちに、終わりのない迷路にはまり込んだ
      結局、私の systemd は単に podman compose up を実行している
      compose に本来の仕事をさせるのと比べて、Quadlet の利点が何なのか気になる
      ちなみに Podman は自分のユーザーで実行されており、デーモンはまったくない
    • 開発用のコツは Podman ソケット を有効にし、ルートレスコンテナならユーザー単位で有効にしたうえで、スタンドアロンの docker-compose を使うことだ
    • Windows や Mac では systemd を使えないので、結局 podman compose だけが残る
  • 最近 Quadlet を見つけて、atomic OS とルートレス Quadlet をベースにホームラボ全体を作ったが、強くおすすめする
    systemd のソケットアクティベーションも可能で、たとえば systemd の http/https ソケットを作り、ssh.socketpodman.socket がそれぞれ sshd.servicepodman.service を有効化するように、Traefik を自動で有効化できる
    ルートレス構成で元の IP を保持する実質的に唯一の方法なので、命綱に近い。ルートレス Podman/Docker は通常、大きな欠点なしに元の IP の保持を簡単には許可しない
    https://github.com/savely-krasovsky/homelab

    • Traefik が有効化されるまでにどれくらいかかるのか気になる
  • Quadlet は、「本番環境に近い環境で相互依存するコンテナ群をすべて実行する」という docker compose の用途には良い代替手段です。
    ただし、docker compose のもう一つの用途である開発用途については、もっと良くなってほしいところです。
    docker compose なら、データベース、Redis、OpenSearch、その他の依存関係、nginx プロキシ、.:/app をボリュームとしてマウントした開発用コンテナをまとめて起動し、まとめて削除でき、docker-compose.yml をリポジトリに入れられます。
    Quadlet はすべてのファイルを ~/.config/containers/systemd に置くよう求めるため、もはやプロジェクト内に隔離されず、他の開発者とチェックインして共有するのにも便利ではありません。加えて、彼らも Podman を使う必要があります。
    ほとんどの人はまだ Docker を使っており、Codespaces のようなホスト型開発環境でも Docker が提供されています。
    そのため、チェックインされた YAML ファイルで docker compose を使っています。私は Podman を使っているので、すべてのボリュームに手動で :Z を付ける必要がありますが、通常の Docker はそれを処理できません。
    開発用の docker compose 代替があるとよいのですが、Quadlet はあまり合っていないように見えます。

    • podman-compose --in-pod=1 systemd -a create-unit を使うと podman-compose@ サービスを作成でき、その後 podman-compose systemd -a registercompose.yml ファイルを $name とともに登録できます。
      すると podman-compose@$name.service で compose ファイルベースの pod を管理でき、完全にルートレスでも動作します。
    • この場合に探しているものは Podman pod であり、私なら全体を Ansible でオーケストレーションしたうえで、Ansible プレイブックを全員に配布してローカルで実行してもらいます。
    • systemd-run は任意のコマンドを基に 一時的な systemd サービス を実行できるようにしてくれます。
      必要ならタイマーまで含めて、systemd のスコープ規則に従うきれいな一時ユニットを作ってくれます。
      [1] https://www.freedesktop.org/software/systemd/man/systemd-run...
    • Quadlet は概ね デプロイ用途 に近いものだと思います。compose の代替を探しているなら、Podman Kube Play[1] を見るほうがよいでしょう。
      Kubernetes に似た形式に、コンテナビルドなどの便利機能が少し追加されています。
      kube play ファイルをプロジェクトルートに置き、podman kube play project.yaml --build を実行すると、pod やボリュームなどが一緒に実行されます。
      Quadlet ファイルはデプロイ段階で有用です。プロジェクトを VPS に載せたいなら、すでに持っている project.yaml とともに Kube Quadlet[2] を使えばよいです。
      [1] https://docs.podman.io/en/latest/markdown/podman-kube-play.1...
      [2] https://docs.podman.io/en/latest/markdown/podman-systemd.uni...
    • うちの会社でも開発に docker-compose.yml を使っているので、そのつらさは分かります。
      概ねとてもよく動きますが、OSX ではあの忌々しい中間 VM のせいで、ときどき妙な挙動をすることがあります。
      たまに Podman 互換性を確認していますが、今ではルートレスの哲学があまりにも違うため、完全互換は不可能だと受け入れています。
      それでもこのツールは本番環境には素晴らしいです。趣味プロジェクトをいくつかベアメタルノード上で自作の systemd サービスとして動かしており、現在はユーザーモードの containerd です。
      時間ができたら移行してみるかもしれません。
  • この記事が Podman-Compose を「活発にメンテナンスされていない」とし、最後のコミットが5か月前だと指摘しておきながら、すぐ代替として最後のコミットが同じく5か月前の Podlet を勧めているのが面白い
    Podlet は有用かもしれないが、Docker Compose の多くの機能をサポートしておらず、常にきれいに変換してくれるわけでもない
    特に -f docker-compose.yml -f docker-compose.override.yml のように複数の YAML ファイルを重ねる機能をサポートしていない

    • compose ファイルが好きなら、Docker の compose アプリケーション[1]を Podman[2] と組み合わせて使える
      compose CLI はソケット経由でエンジンを制御しているようで、Podman と Docker エンジンはほぼ同じ API を持っている
      podman-compose が期待どおりに動かなかったので、この方法を使っている
      Docker-compose は通常 docker クライアントプラグインとしてインストールされるが、私は Podman と使うためにスタンドアロンアプリケーションとして使っている
      また、連携設定には DOCKER_HOST 環境変数より docker contexts を好んで使っている
      純粋な Quadlet だけでは十分に強力でないなら、Quadlet[3] と通常の Podman[4] も限定的な Kubernetes マニフェストの実行をサポートしている
      まだ compose ファイルの restart オプションを Podman がどう扱うのかは把握できていない。Podman には監視デーモンがないためだ
      一方で healthcheck オプションは systemd タイマーに依存していることは知っている
      systemd ではないディストリビューションである Gentoo で Podman を使ったとき、自動ヘルスチェックは動かなかったが、手動でヘルスチェックを実行すると残りの設定は最後まで進んだ
      [1] https://github.com/docker/compose
      [2] https://docs.podman.io/en/latest/markdown/podman-system-serv...
      [3] https://docs.podman.io/en/latest/markdown/podman-systemd.uni...
      [4] https://docs.podman.io/en/latest/markdown/podman-kube-play.1...
    • 公平に見れば、Podlet の機能は継続的な更新を必要としないが、podman compose はそうではない
      Podlet は補助ツールであり、長期的には Quadlet で作業するほうがよい
    • コミット日時は何かがメンテナンス中であることを示すには正確ではないが、メンテナンスされていないことを示すことはできる
      5か月はメンテナンスされていないという意味ではなく、2年くらいは必要だ
      それでも懸念を強めはする。ただし、5か月というのはメンテナンス中である証拠には決してならない
      メンテナンスされていないリポジトリにも更新される理由はいろいろあり、最近のいまひとつな GitHub のアーカイブ機能だけがそれを防いでくれる
  • 数年前にセルフホスティング構成を初期化する際、別のものを試したくて openSUSE MicroOS を選び、結局 systemd/Quadlet の下で Podman コンテナを動かすことになったが、現在の構成にはかなり満足している
    コンテナは Podman 内蔵ツールで自動更新され、ログ確認と監視は普段の systemd ツールで処理している
    何かを変更する必要があるときも、設定ファイルの場所を忘れていても見つけやすく、読みやすく修正もしやすい
    ルートレスでデーモンレスなのも良い
    途中でいくつか試したが、podman compose は鈍重に感じられ、deprecated になったのは歓迎で、Quadlet が進むべき道であることは明らかだ
    学習曲線があり、Docker より資料が少ない点は考慮する必要がある
    ローカル開発で複数サービスのスタックを立ち上げたり停止したりする用途なら、今でも Docker と docker compose のほうを選ぶ

    • 安価な古いワークステーションで Fedora CoreOS を使い Nextcloud を動かしている
      設定を合わせるのには少し時間がかかったが、メンテナンスがほとんど不要な点に非常に感銘を受けた。今のところはまったく不要だった
      同じように試したい人は私の設定を参考にできる
      https://github.com/jeppester/coreos-nextcloud
    • Quadlet + MicroOS の組み合わせは非常に強力で、Fedora CoreOS のような他の atomic ディストリビューションでも同様だ
      すべてのノードをゆっくり MicroOS に移行しているところで、会社でも MicroOS かそれに近いものを推している
      ベース OS の自動ロールバックと、宣言的なコンテナ設定および自動更新の組み合わせが、互いにぴったり噛み合っている感じがする
  • 形式は podman generate systemd や Kubernetes YAML よりも明確で、systemd 統合も素晴らしい
    いら立たしいのは、Podman upstream が Debian/Ubuntu 向けリポジトリを提供していないことだ
    Debian stable では 4.3.1 に縛られて新機能を多く逃し、結局 Docker compose に戻ることにした

    • Debian を動かしている Raspberry Pi で Quadlet を使おうとして同じ問題に遭遇した
      提案された回避策は Podman を自分でコンパイルするか、debian/testing を使うことだった
  • この新しいアプローチが、人々がDockerからPodmanへ移行する助けになることを心から願っています。
    Docker Composeは多くの人が移行をためらう理由で、私もそうでした。
    正直なところ、Quadlet以前のPodmanにはきちんとした答えがありませんでした。
    Docker Composeが理由でDockerからの移行をためらっていたなら、Quadletを組み合わせたPodmanはずっと対抗しうる代替案です。
    思ったほどDockerが恋しくなることはなく、ルートレスコンテナの実行によるセキュリティ向上も得られます。

    • 複数の独立したQuadlet環境を持てるようになるまでは移行しません。
      すべてを~/.config/quadlet/systemdに入れる方式ではだめです。
      開発とテストにはこの点が必須で、現状のQuadletは厳密にはデプロイ用ソリューションです。
  • Quadletはコンテナを通常のシステムサービスのように扱えるようにしてくれるので、本当に気に入っています。
    ただし、ルートレスコンテナのユーザー体験はこの概念化とうまく合いません。
    通常、システムサービスはシステムのsystemdセッションでシステムユーザーとして実行されますが、ルートレスコンテナのサービスはシステムユーザーのユーザーsystemdセッションに存在します。
    システムセッション内でルートレスQuadletを実行できるとよいのですが。

    • user-lingerを有効にして、ユーザーsystemd経由でルートレスに実行するのと実質的な違いがあるのか気になります。
      私はいつもそうしてきました。
    • 私もシステムセッション内でルートレスQuadletを実行できるとよいと思います。
      また、DynamicUser=オプションでルートレスQuadletを実行できるとよいです。
      DynamicUser=はシステムサービスの権限を制限する優れた方法でしたが、今のPodmanとはあまり相性がよくありません。
  • Hacker NewsのトップページでQuadletを見かけて興味深いです。十分に注目されていないと思います。
    プロジェクトのYgalとValentinが、inletsトンネルクライアントを実行する方法についてゲスト記事を送ってくれたことがあります。Ngrok/Cloudflaredに似ていますが、SaaSの制限なしでセルフホストする方式です。
    https://inlets.dev/blog/2023/10/03/client-quadlet.html
    彼らは[container]の代わりに[kube]を使うことで標準のKubernetes YAMLを持ち込め、かなり移植性が高くなりました。

  • 興味のある人向けに、最近のQuadletデプロイがどれほど簡単かを示すAnsibleテンプレートを作りました。
    GH: https://github.com/Mati365/hetzner-podman-bunjs-deploy