0

NASでDocker Composeを使った高度な遊び

Share
  • 11月 2, 2025

私のことをよくご存知の方は、私がよくNASを弄っていること、そしてDockerが不可欠な多くのセルフホスト・サービスのNASデプロイメントにも参加していることをご存知でしょう。異なるNASシステムには異なるDockerソリューションがあり、Docker Composeは現在最も広く適用されているものです。

ラベルの説明

Docker Composeの設定ファイルはYAML形式で、通常はdocker-compose.ymlまたはcompose.yamlファイルです。トップレベルタグは、アプリケーション全体のサービス、ネットワーク、ストレージボリュームなどの設定を定義します。以下は、Docker Compose設定ファイルにおける一般的で重要なトップレベルタグ名とその機能の一覧です。このリストはCompose仕様に基づいており、古いv2およびv3形式に代わるもので、現段階で推奨され、広く使われている標準です。

バージョン (非推奨)(新しい Compose 仕様では推奨されなくなりました) 古い Compose ファイル形式 (v2 および v3) で、プロファイルのバージョンを指定するために使用されます。現在では、Compose仕様を使用する場合、このフィールドは省略されるか、後方互換性のためにのみ使用されます。旧バージョン
サービスアプリケーションのすべてのサービスを定義します。 各サービスのエントリ( imagecontainer_nameなど )は、このキーの下のサブ設定として動作します。これがComposeファイルの核となる部分です。強制的
ボリューム名前付きボリュームを定義する。 これらのボリュームは異なるサービス間で共有でき、コンテナのライフサイクルに依存しない。選択可能
ネットワークカスタムネットワークの定義。 サービス同士または外部ネットワークと通信するために、サービスが特定のネットワークに接続できるようにします。選択可能
コンフィグ構成データの定義。 一般的にアプリケーションのコンフィギュレーションに使用される、機密または非機密のコンフィギュレーション・データにサービスがアクセスできるようにする。選択可能
秘密機密データ(Secrets)を定義する。 パスワードやAPIキーなどの機密情報にサービスが安全にアクセスできるようにする。選択可能
含む追加のComposeファイルが含まれています。 コンフィギュレーションを複数のファイルに分割して、簡単に管理・再利用できるようにします。選択可能
名称プロジェクト名を指定します。 ディレクトリ名をプロジェクト名とするデフォルトの動作を上書きするために使用します。選択可能

これらのトップレベルタグのうち、servicesタグは コンテナを構築するのに不可欠であり、その下に多くの共通サブタグがある。

イメージコンテナのビルドに使用するイメージを指定します。 Docker Hub上のパブリックイメージ、プライベートリポジトリ、ローカルイメージのいずれかを指定します。
ビルドイメージのビルド方法を定義します。 既存の イメージを使用しない場合は、Dockerfileのパスとビルドコンテキストを指定します。
コンテナ名コンテナの固定名を指定します。 デフォルトでは、Compose は名前を生成します(例: projectname-servicename-1)。
ポートコンテナのポートをホストに公開する。 形式は通常、 ホストポート:コンテナポートである。
ボリュームストレージボリュームまたはホストパスをコンテナにマウントする。 データ永続化または共有ホスト・ファイルに使用する。フォーマットは、 ホスト・パス:コンテナ・パス または ボリューム名:コンテナ・パスである。
環境コンテナに環境変数を設定する。 これは、キーと値のペアのリストか、ファイル参照である。
環境ファイルファイルから環境変数を追加する。
ネットワークサービスが接続すべきネットワークを指定する。
depends_onサービス間の依存関係を定義する。 現在のサービスが開始される前に、依存するサービスが開始されるようにする。
リスタートコンテナ終了時の再起動ポリシーを定義する。 例として、 alwayson-failureunless-stoppedがある。
命令コンテナの起動時に実行されるデフォルトのコマンドを上書きする。
エントリポイントコンテナのデフォルトのエントリーポイントをオーバーライドする。
ラベルコンテナにカスタムメタデータ(タグ)を追加する。
ヘルスチェックコンテナの健全性ステータスをチェックするコマンドを定義する。
伐採サービスのロギングドライバとオプションを設定する。
配備デプロイと実行時の制約を指定する(主にスウォームモードで使用)。

わかりやすくするために、2つのサンプルを使って説明しよう。それぞれのタグの横に # マークでコメント(メモ)をつけておく。

次の例は、スタンドアロンのウェブ・サーバー・コンテナ(Nginx イメージを使用)を単一コンテナで構成するシナリオを示している。

# Compose ファイルのトップレベル設定キー(タグ)

# 最新の Compose Specification に従うため、通常 'version' キーは非推奨です。
# 後方互換性が必要な場合は、次のように追加できます(ただし非推奨):
# version: '3.8'

# コアタグ:アプリケーション内のすべてのサービスを定義します
services:
  # サービス名:任意の名前を付けられます。ネットワークエイリアスとして機能します
  web_server:
    # サービスサブタグ:

    # コンテナの構築に使用するイメージを指定します
    image: nginx:latest

    # コンテナに固定の名前を割り当てます
    container_name: my_single_nginx_container

    # ボリュームまたはホストパスをコンテナにマウントします
    # 形式:[ホストパスまたはボリューム名]:[コンテナ内部パス]
    volumes:
      # ローカルの ./html ディレクトリを、コンテナ内の Nginx のデフォルトウェブディレクトリにマウント
      - ./html:/usr/share/nginx/html:ro

    # コンテナのポートをホストに公開します
    # 形式:[ホストポート]:[コンテナポート]
    ports:
      # コンテナの 80 ポートをホストの 8080 ポートにマッピング
      - "8080:80"

    # コンテナ内の環境変数を設定します
    environment:
      # これは環境変数の例です
      - TIMEZONE=Asia/Shanghai

    # コンテナ終了時の再起動ポリシーを定義します
    # 'unless-stopped' は、手動で停止されない限り、コンテナ終了時に再起動することを意味します
    restart: unless-stopped

    # コンテナにカスタムメタデータ(ラベル)を追加します
    labels:
      - "com.example.description=Single Nginx Web Server"

# トップレベルタグ:名前付きボリュームを定義します(必要な場合)
# この単一コンテナの例では、ホストマウントを使用しているため、'volumes' タグは省略可能です。
# volumes:
#   my_data:

# トップレベルタグ:カスタムネットワークを定義します(必要な場合)
# この単一コンテナの例では、Compose はデフォルトのブリッジネットワークを使用します。
# networks:
#   default:
#     driver: bridge

この例では、Web アプリケーション(Node.js の例)とデータベース(PostgreSQL を使用)を複数のコンテナで構成し、それらの間の依存関係と通信を設定します。

# Compose ファイルのトップレベル設定キー(タグ)

# コアタグ:アプリケーション内のすべてのサービスを定義します
services:
  # サービスその一:ウェブアプリケーション
  app_service:
    # サービスサブタグ:

    # イメージの構築方法を指定します(Dockerfile から構築)
    # 'context' は Dockerfile があるディレクトリ、'dockerfile' は Dockerfile のファイル名を指定
    build:
      context: .
      dockerfile: Dockerfile.app

    # コンテナに固定の名前を割り当てます
    container_name: web_app_container

    # コンテナのポートをホストに公開します
    # コンテナの 3000 ポートをホストの 3000 ポートにマッピング
    ports:
      - "3000:3000"

    # コンテナ内の環境変数を設定します
    environment:
      # データベース接続に必要な環境変数
      - DB_HOST=db_service  # 接続用のホスト名としてサービス名を使用
      - DB_PORT=5432
      - DB_USER=user
      - DB_PASSWORD=secret

    # サービス間の依存関係を定義します
    # db_service コンテナが起動し実行されてから app_service を起動することを保証
    depends_on:
      db_service:
        condition: service_started

    # サービスが接続すべきネットワークを指定します
    networks:
      - internal_network
      - public_network

  # サービスその二:データベースサービス
  db_service:
    # サービスサブタグ:

    # 使用するデータベースイメージを指定します
    image: postgres:14-alpine

    # コンテナに固定の名前を割り当てます
    container_name: postgres_db_container

    # ボリュームをコンテナにマウントします
    volumes:
      # データ永続化のために名前付きボリュームを使用し、コンテナ再起動後もデータが失われないようにします
      - postgres_data:/var/lib/postgresql/data

    # ファイルから環境変数を追加します(機密情報を管理するより安全な方法)
    # POSTGRES_USER などの変数を含む .env.db というファイルが存在することを想定
    env_file:
      - .env.db

    # コンテナ終了時の再起動ポリシーを定義します
    restart: always

    # サービスが接続すべきネットワークを指定します
    # 注意:データベースサービスは通常、パブリックに直接公開されず、内部ネットワークのみに接続します
    networks:
      - internal_network

# トップレベルタグ:名前付きボリュームを定義します
volumes:
  # 'postgres_data' という名前のボリュームを定義
  postgres_data:
    # ドライバーやオプションを指定できますが、ここではデフォルトドライバーを使用
    driver: local

# トップレベルタグ:カスタムネットワークを定義します
networks:
  # アプリと DB の通信に使用する内部ネットワークを定義
  internal_network:
    driver: bridge
  # 外部接続が必要になる可能性のあるネットワークを定義
  public_network:
    driver: bridge

NASで使用

現在、すべての主流のNASシステムはDocker Composeをサポートし、自分のニーズに応じて、対応するプロジェクトのDocker Composeを見つけ、コピーしてNASのDocker Composeに貼り付け、自分の特定の状況に応じて編集することができます。

特別な注意点として、Docker Composeを自分のNASで使用する場合は、Docker Composeファイル内のパスを変更することです。先に述べた マウントタグボリュームと 変数ファイルenv_file タグは、どちらもパスの設定に関係しています。ほとんどのNASシステムでは、Docker Composeを追加する際にパスを設定する必要があり、このパスがコンテナプロジェクトがNAS内のファイルを保存する場所になります。

Docker Composeファイルでは、各タブの項目は「:」で区切られており、1つ前のコロンがマッピングされたホストのポートまたはアドレス、1つ目のコロンの後がコンテナ内のポートまたはアドレス、2つ目のコロンの後が読み書き権限などの設定項目である。

開発者のコード編集の癖によって、マウントアドレスをマッピングするとき、絶対アドレスを書く開発者もいれば、相対アドレスを書く開発者もいる:

絶対アドレス:/volume1/docker/Test/html

相対アドレス:./html

上記の例では、 html フォルダがマップされたマウント・フォルダであり、”. . /」は htmlフォルダが /docker/Test ディレクトリにあることを意味する。個人的には、コンテナやdockerディレクトリが再配置されても、ディレクトリがなくなってコンテナが無効にならないように、相対パスを使う方が好きだ。

もう1つはポートで、上の例では、コンテナ内のポート80をホスト上のポート8080にマッピングしています。NAS内で複数のDockerコンテナが実行されている場合は、どのポートがすでに占有されているかに注意し、異なるコンテナで同じポートをマッピングしないようにしてください。