ホームラボにおけるDocker Compose:構成、プロファイル、およびベストプラクティス

最終更新: 月24 2026
  • Docker Composeをプロファイルとロールごとに整理することで、数十ものサービスを含むホームラボの管理が簡素化されます。
  • .envファイルに設定を一元化し、オーバーライドを使用し、Gitでバージョン管理を行うことで、環境の移植性と移行の容易性が向上します。
  • 専用ネットワーク、Traefik、およびヘルスチェックにより、サービスの安全性、隔離性、および回復力が向上します。
  • 監視機能、管理されたログ、自動バックアップ機能により、ホームラボは長期的に安定したプラットフォームとなる。

Docker Compose Homelab

コンテナを使った最新のホームラボ環境を構築することは、多くの技術者にとって人気の趣味となっています。この環境構築の中心となるのは、ほぼ間違いなくDocker Composeです。YAMLでサービスを定義し、Gitでバージョン管理を行い、たった1つのコマンドで環境全体を起動できます。

しかし、規模が大きくなるにつれて状況は変化します。コンテナが2、3個から、数十個のサービス、内部ネットワーク、リバースプロキシ、データベース、CIランナーへと増えていきます。そこで大きな疑問が生じます。巨大な単一のDocker Composeインスタンスを使うべきか、それとも多数の小さなファイルを使うべきか?プロファイル、ネットワーク、バックアップ、セキュリティをどのように整理し、さらに移行を容易にするにはどうすればよいのか?

ホームラボでDocker Composeをセットアップするための実践的なアプローチ

Docker Composeを使用したホームラボのセットアップ

実際には、Homelabsをしばらく利用している人は、それぞれに長所と短所がある3つの異なるCompose組織モデルを使い分けていることが多いです。適切なアプローチを選択することで、規模を拡大したり新しいマシンに移行したりする際に、多くの手間を省くことができます。

一方で、スタンドアロンのDocker Runコマンドから始めて、Portainerに移行し、最終的にDocker Composeに飛びついた人もいます。これは典型的なシナリオです。Portainerは優れた可視性、ユーザーフレンドリーなインターフェース、テンプレートなどを提供しますが、最終的には、ファイルに何も記述されていないと、複雑なパラメータの編集や構成の移行が面倒になります。

その反対の極端な例として、リバースプロキシ、メディア、ユーティリティ、モニタリング、LLM、データベースなど、ホームラボのすべてのサービスを実行できる単一の「メガ」docker-compose.ymlにすべてを統合した人がいます。すべてが単一のスタックに収まります。

その中間として、多くのユーザーは混合アプローチを採用しています。つまり、コンテキスト(メディア、インフラストラクチャ、生産性、監視など)ごとにグループ化された複数の小さなdocker-compose.ymlファイルを同じリポジトリに配置し、通常はグローバル環境変数を共有します。

両方の利点を兼ね備えた、実に洗練された解決策があります。それは、他のファイル(それぞれがアプリやサービスのサブフォルダ内)を含む「ルート」docker-composeファイルを作成することです。こうすることで、ホームラボ全体の状況を把握しながらも、読みにくい1000行ものYAMLファイルに悩まされることもありません。

プロファイル、機能別グループ化、大規模ホームラボ

docker compose homelab プロファイル

ホームラボのサービス数が30、40、50個(データベース、キャッシュ、インデクサーなどのバックアップサービスを含む)に近づくと、それらを整理することが不可欠になります。そこで、機能ごとにグループ化することと、 Docker Composeプロファイルを使用することが有効になります。

よくあるパターンとしては、すべてを単一のCompose「プロジェクト」にまとめ、プロファイルごとに論理的に分割する方法があります。例えば、次のようになります。

  • コアプロファイルホームラボの中核となる構成で、リバースプロキシとしてTraefikを使用し、同一ドメイン内のすべてのアプリをHTTPSで認証するためのIDプロバイダー(OAuthやAuthentikなど)を備えています。
  • メディアプロフィールPlex、Sonarr、Radarr、Ombi、SABnzbd、qBittorrentなどのサービスは、マルチメディアコンテンツのキュレーション、ダウンロード、配信を担当します。
  • 公益事業概要コンテナやアップデートの管理・監視には、Portainer、Watchtower(使用する場合)、Diun、dockcheckなどのツールを使用します。
  • インフラストラクチャ/監視プロファイルTraefik、cAdvisor、Prometheus、Grafana、Uptime Kuma、Dozzle、および監視とログ記録に関連するすべてのもの。
  • 実験プロファイルまたはLLM: LLM や興味深いアプリ (ChatGPT Next Web local、LibreOffice Online など) 用の特定のスタックで、通常はデフォルトで無効になっています。

プロファイルの利点は、必要に応じてインフラストラクチャの一部のみをデプロイできる点です。例えば、低消費電力のミニPCではコアとインフラストラクチャのプロファイルのみを実行し、ディスクやGPUを多く搭載した大型サーバーではメディアプロファイルのみをデプロイするといったことが可能です。

適切に設計されたリポジトリでは、通常、ルートに「master」というdocker-compose.ymlファイルがあり、includeを使用して個々のファイルをapps/またはservices/フォルダにプッシュします。さらに、ほぼすべてのサービスは単一のグローバルな.envファイルで設定され、一部のシークレットはsecrets/ディレクトリに保存されるため、初期設定が大幅に簡素化されます。

このパターンに従うと、ホームラボの管理は基本的に.envファイルとシークレットの編集、プロファイルの有効化または無効化、各ホストで起動するサービスの決定に集約されます。これは、同じアプリケーションセットを複数のマシンに展開する場合に最適です。

巨大な単一のdocker-composeファイルと、複数の小さなファイル

Docker Compose Homelab ファイル構造

これは永遠の議論です。すべてを1つのdocker-compose.ymlファイルにまとめるべきか、それともサービス/スタックごとに複数のファイルを作成するべきか?実際の答えは通常、「移行の容易さを優先するか、サービスごとの明確さを優先するかによって決まる」ということになります。

単一のマスターファイルを支持する人々は、通常、いくつかの利点を強調する。

  • ホストの移行はとても簡単ですリポジトリをクローンし、.env ファイルとシークレットをコピーし、ボリュームをマウントして、`docker compose up -d` を実行します。ディレクトリごとに操作する必要はありません。
  • 真実の規範としてのインフラストラクチャホームラボのトポロジー全体(サービス、ネットワーク、ボリューム、依存関係)が1か所にまとめられています。
  • 集中更新イメージのバージョン、再起動ポリシー、ログ記録などを変更する場合、どこをいじればよいか正確にわかります。
  IT危機:歴史、大規模停電、そして現在の影響

しかし、それには明らかな欠点もあります。巨大なYAMLファイルは保守が難しくなり、マージの競合が増加し、特定の問題をデバッグする際には、何百行にも及ぶ巨大なコードと格闘しなければならなくなります。すべてが大きくなりすぎると、少し後悔する気持ちになるのはよくあることです。

もう一つのアプローチは、次のような構造で、アプリケーションごと、または論理スタックごとにdocker-compose.ymlファイルを用意することです。

docker/
├── bookstack/
│   └── docker-compose.yml
├── dashy/
│   └── docker-compose.yml
└── traefik/
    └── docker-compose.yml

これにより、各コンテナにはbookstack-app-1やtraefik-reverse-proxy-1のような名前が付けられ、問題の特定が容易になります。例えば、bookstack-app-1 コンテナがクラッシュした場合、どのフォルダを調べればよいかがすぐにわかります。

視覚的にもはるかにすっきりしており、各サービスを個別に管理できます(他のサービスに影響を与えることなく、起動、停止、更新が可能です)。さらに、Dozzleのようなアプリケーションは、ログをより適切に整理するために、個別のスタックを活用しています。

デメリットとしては、すべてを分離しすぎると、共通サービス(Traefikや共有ネットワークなど)間の連携に少し注意が必要になることです。外部ネットワークや特定のTraefikラベルを宣言し、他のdocker-composeによって作成されたネットワークの命名規則を覚えておく必要があります。

.env、オーバーライド、バージョン管理に関するベストプラクティス

最も過小評価されているテクニックの1つは、設定を.envファイルに一元化することです。docker-compose.ymlに環境変数を大量に記述する代わりに、次のように定義します。

DB_USERNAME=myuser
DB_PASSWORD=secretpassword

そしてYAMLファイル内では、${DB_USERNAME}または${DB_PASSWORD}として参照されます。これにより、Composeは一目で読みやすくなり、複数のサービス間で変数を共有できるようになり、そして最も重要なことに、パスワードは別のファイルに保存されます(このファイルはGitから除外できます)。

さまざまな環境(本番環境、テスト環境、開発環境)に対応するには、 docker-compose.override.yml を活用すると非常に便利です。基本的な docker-compose.yml ファイルを用意し、override ファイルではポート、パス、デバッグフラグなど、変更が必要な部分のみを上書きするという考え方です。

例えば、開発環境では、異なるポートを公開したり、デバッグを有効にしたり、ローカルのソースコードをマウントしたりするオーバーライドを読み込むことができます。メインのYAMLファイルには手を加えず、実行環境に合わせてスタックを調整します。

言うまでもなく、ホームラボを少しでもプロフェッショナルなものにしたいなら、Gitで全てをバージョン管理することは必須です。通常は次のような構成になります。

homelab-docker/
├── docker-compose.yml
├── .env.example
├── services/
│   ├── media/
│   ├── infra/
│   └── ...
└── scripts/

そこからリポジトリを初期化し、インフラストラクチャの変更をコミットすれば、何か問題が発生しても、数秒でComposeの以前のバージョンに戻すことができます。本格的なホームラボにとって、これは単なる選択肢ではなく、気が狂いそうになるのを避ける唯一の方法です。

ネットワーク、Traefik、およびセキュアサービスの露出

中級レベルのホームラボのほぼすべてにおいて、同じ組み合わせが見られます。それは、リバースプロキシとしてTraefik、そして集中型IDプロバイダー(AuthまたはAuthentik)を使用する構成です。これにより、HTTPSとSSOを備えたサブドメインで多数のアプリケーションを公開することが可能になります。

一般的なアプローチとしては、リバースプロキシなどの専用のDockerネットワークを構築し、そこにTraefikと外部に提供するすべてのWebサービスを接続する方法があります。残りのコンテナ(データベース、キャッシュなど)は、隔離された内部ネットワーク上に配置します。

Traefikを使用し、サービスを複数のDocker Composeインスタンスに分割する場合は、共有外部ネットワークを定義する必要があります。例えば、次のようなものです。

services:
  bookstack:
    image: lscr.io/linuxserver/bookstack
    networks:
      - traefik-net
    labels:
      - "traefik.docker.network=traefik_default"

networks:
  traefik-net:
    name: traefik_default
    external: true

ここでは、traefik_default ネットワークは Traefik スタックによって作成され、他のサービスは traefik-net と呼ばれる外部ネットワークを介して追加されます。ラベルは、トラフィックのルーティングに使用するネットワークをTraefik に指示します。

単一のスタックにバックエンドサービス(例えば、Webコンテナとそのデータベース)が含まれる場合、それらを共有のデフォルトネットワークに接続し、WebコンテナのみにTraefikネットワークへのアクセス権限を付与することができます。データベースには`traefik.enable=false`というラベルが設定されるため、Traefikはデータベースを無視します。

このタイプの構成には、サービス間の分離と制御された公開という2つの重要な利点があります。Traefikラベルが付与され、プロキシネットワーク上にあるコンテナのみが外部からアクセス可能になります。

データ永続性、ボリューム、およびディスク構造

永続データのないホームラボはあまり役に立ちません。データベース、設定、メディア、ドキュメントなど、すべてがDocker Composeのダウン後も存続する必要があります。ボリュームとバインドマウントは、まさに生命線です。

  Apple WatchのアップデートとwatchOSの新機能に関する完全ガイド

多くの人は、次のような構造で収納を整理しています。

/mnt/storage/
├── downloads/
│   ├── movies/
│   └── tv/
├── media/
│   ├── movies/
│   ├── tv/
│   └── music/
└── srv/
    └── 

つまり、ダウンロードツール(qBittorrent、SABnzbdなど)はダウンロードフォルダのみを参照し、Radarr/Sonarrのようなマネージャーはダウンロードとメディアの両方にアクセスでき(ハードリンクの移動や作成のため)、PlexやJellyfinのようなサーバーはメディアフォルダのみを参照するという仕組みです。

こうすることで、最小権限の原則が適用されます。つまり、各コンテナは実際に必要なものにのみアクセスします。また、明確な分離によって、どのボリュームやパスをクラウドや外部ドライブにバックアップするかを決定する際にも役立ちます。

srv ディレクトリは通常、アプリケーションの設定を保存するために使用されます (例: /srv/jellyfin/config、/srv/traefik、/srv/paperless など)。通常、このディレクトリには部分的にバージョン管理されたファイル (テンプレート、Caddyfile など) が格納され、重要度の高いファイルやリソースを大量に消費するファイルは除外されます。

場合によっては、ダウンロードチェーンにハードリンクを使用することが有効な場合があります。RadarrやSonarrのようなサービスは、ダウンロードしたファイルをリンクすることで、ディスク容量を重複させることなくシード状態を維持できます。TRaSHGuidesなどのガイドで提案されているディレクトリ構造は、まさにこの原則に基づいています。

GitHub Actionsとローカルランナーを使用したデプロイメントの自動化

さらに一歩進んで、CI/CDを使ってホームラボのアップデートを自動化することも可能です。多くのユーザーが、JenkinsなどのツールをGitHub Actionsとホームラボ内で自己ホストするランナーを使ったワークフローに置き換えています。

仕組みはシンプルです。ホームラボのリポジトリのメインブランチにプッシュするたびに、GitHub Actionsワークフローが起動され、テストやリンターが実行され、すべてがうまくいけば変更がサーバーにデプロイされます。

一般的なワークフローには、次のような手順が含まれます。

  • Gitleaksタイプの秘密スキャナー: 誤ってパスワードやトークンをリポジトリにアップロードしてしまった場合。
  • リンティング YAMLやインフラストラクチャコードの読みやすく一貫性のある形式を維持するため。
  • ホームラボ内のリポジトリを更新する: 対象サーバーでgit pullを実行します。
  • コンテナの制御された再生成古いものを停止し、新しいものを起動して、ステータスを確認してください。

利点:セキュリティの向上(機密情報の漏洩を制御できる)、コード品質の向上、そして1回のプッシュで繰り返しデプロイが可能。さらに、ローカルランナーを使用するため、イメージやボリュームがネットワーク外に出ることはなく、GitHubインターフェースを活用してパイプラインを視覚化できます。

Docker Composeがホームラボでの作業を格段に楽にする理由

多くの人が長年Docker RunとPortainerに頼ってきましたが、何らかの障害や移行が発生した後、そのアプローチを見直さざるを得なくなりました。ホストを失ったり、サービスを別のマシンに移行したりする必要がある場合、Portainer内の個別のコマンドや設定だけに頼るのは落とし穴です。

Composeに切り替える際の大きな違いは、サービス定義全体がテキストになることです。ボリューム、ポート、ネットワーク、ラベル、変数など、すべてがYAMLファイルにまとめられ、コピー、共有、バージョン管理、再利用が可能になります。

サービスの編集はもはや「コンテナを手動で再構築する」ことではありません。ファイル内の1行を変更して保存し、`docker compose up -d`を実行するだけで済みます。元のコマンドを覚えておく必要も、Portainerの複数の画面を操作して進む必要もありません。

さらに、複数のサーバー(ミニPC、NAS、デスクトップなど)を扱う場合、同じComposeファイルを別のマシンにコピーし、4つのパスを調整して、異なるハードウェア上で同じスタックを実行できるのは非常に便利です。実際、データ損失や混乱した移行といったトラブルを経験した後、Composeのおかげでその後の作業時間を大幅に節約できたという声が多く聞かれます。

さらに嬉しいことに、既存のサービスから新しいサービスを構築するのも非常に簡単になります。例えば、Plexの設定を複製してJellyfinをセットアップする場合、同じメディアパスとトランスコーディングデバイスを再利用すれば、YAMLブロックをコピーするだけでわずか数分で済みます。

最適化: コンテキストの構築、マルチステージビルド、およびリソース

Homelabコンテナの多くは公開イメージから作成されていますが、場合によっては独自のイメージをコンパイルする必要があるでしょう。そのような場合、ビルドコンテキストを適切に管理することが重要です。リポジトリ全体をフィルタリングせずにアップロードするのではなく、強力な`.dockerignore`ディレクティブを使用してプロジェクトフォルダのみを対象とすることで、高速かつ軽量なビルドを実現できます。

もう一つ非常に便利なテクニックは、Dockerfileでマルチステージビルドを使用することです。最初のステージでは依存関係をインストールしてコンパイルし、2番目のステージでは必要な成果物のみを小さなベースイメージにコピーします。その結果、不要なツールチェーンやライブラリが引き継がれないため、最終イメージのサイズが大幅に小さくなり、安全性も向上します。

  ルーターにOpenWrtをインストールする方法:完全なステップバイステップガイド

Compose側では、 CPUとRAMの制限を定義するオプションがあります(特にSwarm環境やDockerがこれらのパラメータを尊重する場合)。これにより、リソースを大量に消費するアプリケーションがリソースを占有するのを防ぐことができます。Homelabsでは、これにより設定ミスのあるサービスがシステム全体に悪影響を及ぼすのを防ぐことができます。

再起動ポリシー(再起動:常に、停止されない限り、障害発生時)を忘れないでください。これらのポリシーを設定することで、重要なサービス(リバースプロキシ、VPN、主要データベースなど)が再起動後や一時的な障害発生後に自動的に再起動されることが保証されます。

最後に、古いビルドの残骸、停止したコンテナ、または孤立したボリュームを削除してディスク容量を解放するために、 docker image prune、docker container prune、docker volume pruneなどのコマンドを使用して定期的なクリーンアップタスクをスケジュールすることをお勧めします。

医療サービス、記録および監視

ホームラボがブラックボックスにならないようにするには、ヘルスチェック、制御されたログ記録、監視という3つの重要な側面に取り組むことが重要です。Docker Composeを使用すると、コンテナが正常かどうかを判断するヘルスチェックをサービスごとに宣言できます(`curl -f http://localhost`などのコマンドまたは特定のスクリプトを使用)。

これにより、正常なコンテナのみがトラフィック(例えば、Traefik経由)を受信し、応答しなくなった場合は設定されたポリシーに従って再起動されることが保証されます。これは、最小限の労力で耐障害性を大幅に向上させます。

ログに関しては、json-fileドライバの最大サイズと最大ファイル数の制限を調整することで、ディスクが数ギガバイトものログでいっぱいになるのを防ぐことができます。DozzleのようなWebツールを使えば、ブラウザからすべてのコンテナのログを閲覧できるため、特定のサービスのデバッグに非常に便利です。

メトリクスと継続的な監視のための定番の組み合わせは、cAdvisor + Prometheus + Grafanaです。cAdvisor はコンテナごとに CPU、メモリ、ディスク、ネットワークの使用統計情報を提供し、Prometheus はそれらを定期的に収集し、Grafana はそれらを魅力的なダッシュボードに表示し、異常値が発生した場合はアラートを発します。

適切に構築されたホームラボには、通常、可用性チェック(HTTP、ICMP、TCPなど)のためのUptime Kumaと、重要なデータを他のディスクやクラウドにコピーするためのDuplicatiのような自動バックアップシステムが含まれています。こうすることで、何が起こっているかを把握でき、何か問題が発生した場合でも、重要なデータを失うことを防ぐことができます。

ホームラボのセキュリティとリモートアクセス

どのような設定をDIYで行う場合でも、セキュリティは必須です。多くの人は、NASやそのサービスを外部に直接公開しないことを選択し、VPN経由でリモートアクセスを制限します(WireGuardは、その性能と使いやすさから非常に人気のある選択肢です)。

このモデルでは、ルーターはゲートウェイとして機能します。VPNサーバーに対してはランダムなポートのみが開かれ、接続が確立されると、内部サービスへのすべてのリクエストは暗号化されたトンネルを経由します。この事前フィルタリングがなければ、Traefikもアプリケーションもインターネットに公開されることはありません。

VPNを自分で管理したくない人は、ポートを開放せずに自宅ラボにアクセスするために、 Cloudflare TunnelやTailscaleを利用することがあります。これらは便利な代替手段ですが、プライバシーを最優先事項とする場合は、これらの第三者がどのようなメタデータを収集する可能性があるかを考慮する必要があります。

サーバーとNASのディスクを暗号化し、定期的にパッチを適用し、自動更新を制限することも有効な対策です(多くのユーザーはWatchtowerの使用を避け、手動で更新を管理しています)。確認していない更新によってホームラボの半分が壊れてしまうよりは、多少遅れてもきちんと管理する方がはるかに良いでしょう。

ご覧のとおり、「エンタープライズ」レベルに達する必要はありませんが、ホームラボが情報漏洩の温床になったり、常に不安の種になったりしないよう、最低限のセキュリティと規律を確立することをお勧めします。

結局のところ、Docker Compose を使って本格的なホームラボを構築するには、組織力、常識、そして試行錯誤する意欲が不可欠です。サービスをグループ化し、ネットワークを適切に定義し、Git でドキュメントを作成し、ある程度自動化すれば、単一のコマンドで起動でき、別のマシンに簡単に移行でき、制御不能なジャングルになることなく少しずつ拡張できる環境が完成します。