Docker ComposeからネイティブなSystemdサービスへの移行
Docker Composeは長年、私の信頼できる主力ツールでした。シンプルでYAML構文も直感的であり、期待通りに動作してくれました。しかし、ラボが15以上のサービスに拡大するにつれ、限界に突き当たりました。Dockerをルートレベルのデーモンとして管理することは、不要なセキュリティリスクのように感じられたのです。さらに、停電後のコンテナの起動順序を正しく保つために、壊れやすいシェルスクプロプトや「sleep」コマンドを多用する必要がありました。
最終的に私は Podmanとその秘密兵器であるQuadletに移行しました。Dockerとは異なり、Podmanはデーモンレスです。「ルートレス」コンテナの実行に優れており、管理者権限のない標準ユーザーアカウントでサービスを実行できます。Quadletは、Systemdがネイティブに理解できる構文でコンテナを定義できるようにすることで、このプロセスを簡素化します。短い設定ファイルを記述するだけで、Systemdがログ記録、自動起動、複雑な依存関係のマッピングなどの重労働を処理してくれます。
自分の環境にこれを導入したところ、すぐに安定性が向上しました。SystemdはDockerデーモンよりも効率的にサービスの起動を並列化するため、Raspberry Pi 4の起動時間は15秒近く短縮されました。標準的なLinuxモニタリングツールとの統合もシームレスになりました。
システムへのPodmanのセットアップ
最近の主要なLinuxディストリビューションの多くは、公式リポジトリにPodmanを含んでいます。Ubuntu 22.04、Fedora、またはDebianを使用している場合は、すぐに準備が整います。Quadletの安定性が大幅に向上した、2023年初頭にリリースされたPodmanバージョン4.4以降を使用することをお勧めします。
# Ubuntu/Debianの場合
sudo apt update
sudo apt install podman -y
# Fedoraの場合
sudo dnf install podman -y
インストール完了後、バージョンを確認します:
podman --version
「HomeLab流」の実行方法(ルート以外での実行)を行うには、ユーザーにsubuidとsubgidの範囲が割り当てられているか確認してください。これにより、Podmanはコンテナ内のユーザーを、システムユーザーと重複することなく、ホストマシン上の特定のIDにマッピングできます。
cat /etc/subuid
cat /etc/subgid
出力にユーザー名と 100000:65536 のような範囲が表示されていれば、環境は正しく設定されています。
Docker ComposeからQuadletファイルへの変換
Docker Composeのセットアップでは、通常 docker-compose.yml ファイルを使用します。Quadletでは、.container ファイルに切り替えます。永続ボリュームを使用した標準的なNginxウェブサーバーの設定を見てみましょう。
ベースとなるCompose設定
services:
web:
image: nginx:latest
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html:Z
restart: always
Quadletでの代替:nginx.container
ルートレスのQuadletファイルは ~/.config/containers/systemd/ に配置します。そのディレクトリを作成し、nginx.container という名前のファイルを追加してください:
[Unit]
Description=Nginxウェブサーバー
After=network-online.target
[Container]
Image=docker.io/library/nginx:latest
PublishPort=8080:80
Volume=%h/html:/usr/share/nginx/html:Z
[Install]
WantedBy=default.target
[Container] セクションでは、SystemdのロジックとPodmanの引数を組み合わせます。ここでは、ホームディレクトリを動的に指す %h 指定子を使用しました。これにより、設定ファイルが異なるユーザーアカウント間でもポータブルになります。FedoraやRHELを使用している場合、:Z フラグは不可欠です。これはSELinuxに対し、コンテナが実際にファイルを読み取れるようにラベルを再設定するよう指示します。
ネットワークとボリュームの管理
データベースをパブリックなインターネットから分離するために、隔離されたネットワークが必要な場合があります。これらは .network ファイルを使用して定義できます。バックエンドネットワーク用に db-net.network を作成します:
[Network]
NetworkName=backend-network
.container ファイル内に Network=db-net.network を追加して、サービスにリンクさせます。クリーンでモジュール化された構成になります。
新しいサービスの実行とモニタリング
ここでのワークフローは少し変わります。もはや手動で podman run を使うことはありません。代わりに、SystemdにQuadletファイルを処理させ、バックグラウンドのサービスユニットを生成させます。
変更を登録するために、ユーザーデーモンをリロードします:
systemctl --user daemon-reload
これで nginx.container は標準的なサービスになりました。他のLinuxプロセスと同じコマンドで制御できます:
# コンテナを起動
systemctl --user start nginx
# 起動時に自動開始するように設定
systemctl --user enable nginx
# 実行状態を確認
systemctl --user status nginx
ログの一元管理が最大の利点です。これらはネイティブなユニットであるため、すべてのログは直接 journald に流れます。何が起きたかを確認するために、独自のDockerコマンドを使う必要はありません。単に journalctl を使用するだけです:
journalctl --user -u nginx -f
サービスの常駐設定
ルートレスサービスは通常、SSHセッションをログアウトすると終了してしまいます。HomeLabを24時間365日稼働させるには、ユーザーアカウントの「リンガリング(常駐)」を有効にする必要があります。これにより、ユーザーのSystemdインスタンスが起動時に開始され、アクティブな状態を維持できるようになります。
loginctl enable-linger $USER
検証とトラブルシューティング
サービスがクラッシュした場合は、まず生成されたユニットファイルを確認してください。Quadletは、高レベルの設定を /run/user/1000/systemd/generator/ にある実際のSystemdユニットに変換します。変換結果を適用せずにプレビューするには、ドライランツールを使用します:
/usr/libexec/podman/quadlet -dryrun -user
このコマンドは、構文エラーやパスの不備を問題が発生する前に見つけるための救世主です。リアルタイムのリソース追跡には、引き続き podman stats を使用して、実行中のすべてのコンテナのCPUとRAMの使用状況を素早く確認できます。
Quadletに切り替えることで、コンテナをネイティブなOSサービスとして扱うことができます。アプリがデータベースを待機するように設定するなど、Systemdの堅牢な依存関係管理を、Podmanの安全なアーキテクチャと組み合わせて利用できます。これは、HomeLabの回復力を大幅に高めるプロフェッショナルなアップグレードです。

