ファイル間、プロジェクト間での Compose 設定の共有

読む時間の目安: 6 分

Compose がサポートする設定共有には 2 つの方法があります。

  1. Compose ファイル全体を 複数の Compose ファイルの利用 により拡張します。
  2. 個々のサービスを extendsフィールド を使って拡張します(Compose ファイルバージョン 2.1 まで)。

複数の Compose ファイルの利用

Compose ファイルを複数利用することにすれば、Compose によるアプリケーションを異なる環境、異なる作業フローに合わせてカスタマイズできます。

Compose ファイルが複数ある意味

デフォルトにおいて Compose は 2 つのファイルを読み込みます。 docker-compose.ymlと、必要に応じて編集するdocker-compose.override.ymlです。 慣習としてdocker-compose.ymlには基本的な設定を含めます。 docker-compose.override.ymlファイルは、オーバーライドという表現が含まれていることから分かるように、既存のサービスあるいは新たに起動する全サービスに対しての上書き設定を行うものです。

サービスの定義が両方のファイルに存在した場合、Compose は 設定の追加と上書き に示すルールに従って定義設定をマージします。

複数の上書きファイルがある場合、あるいは上書きファイルが 1 つであってもその名前を別にしている場合、-fオプションを使って、ファイル名を列記して指定することができます。 Compose はコマンドライン上に指定された順に、設定ファイルをマージします。 詳細は docker-composeコマンドリファレンス-fオプションに関する情報を参照してください。

複数の設定ファイルを利用する場合、各ファイルに記述されるパスは、基準となる Compose ファイル(1 つめの-fにより指定された Compose ファイル)からの相対パスである必要があります。 これは上書きするファイルが Compose ファイルとして有効である必要がないからです。 上書きファイル内は、設定項目が部分的に含まれているだけで構いません。 サービスに対する定義部分がどのパスからの相対パスとして定義されているのかといったことを追っていくのは、なかなか難しく理解しづらくなります。 そこでパスを理解しやすくするために、パス指定はすべて、ベースとなるファイルからの相対パスとして定義するものとしています。

利用例

この節では複数の Compose ファイルを利用する標準的な例を 2 つ示します。 1 つは Compose アプリを異なる環境向けに切り替えるもの。 もう 1 つは Compose アプリに対して管理タスクを実行するものです。

異なる環境向けの例

複数の設定ファイルを利用する例としてよくあるのは、開発環境向けの Compose アプリを、本番環境向けなど(本番環境、ステージング環境、CI 環境など)に切り替える場合です。 こういった環境の違いに対応するには、Compose 設定ファイルをいくつかの設定ファイルに切り分けて行います。

まずはサービスの標準設定を行うベースファイルから始めます。

docker-compose.yml

web:
  image: example/my_web_app:latest
  depends_on:
    - db
    - cache

db:
  image: postgres:latest

cache:
  image: redis:latest

この開発環境向け設定の例では、ホストに対してポートをいくつか公開し、ソースコードをボリュームとしてマウントした上で、ウェブイメージをビルドしています。

docker-compose.override.yml

web:
  build: .
  volumes:
    - '.:/code'
  ports:
    - 8883:80
  environment:
    DEBUG: 'true'

db:
  command: '-d'
  ports:
    - 5432:5432

cache:
  ports:
    - 6379:6379

docker-compose upを実行すると、上書き用の設定ファイルが自動的に読み込まれます。

この Compose アプリは、このままでも十分に本番環境向けとすることができます。 ただここでは、別の上書きファイルを生成します(このファイルは別の git リポジトリに含まれているとか、別の開発チームが管理するものであるかもしれません)。

docker-compose.prod.yml

web:
  ports:
    - 80:80
  environment:
    PRODUCTION: 'true'

cache:
  environment:
    TTL: '500'

この本番環境向け Compose ファイルをデプロイするために、以下を実行します。

$ docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

これによって 3 つのサービスすべてがデプロイされますが、利用される設定はdocker-compose.ymldocker-compose.prod.ymlから読み込まれたものです(docker-compose.override.yml内の開発環境向け設定は利用されません。)。

本番環境での Compose 利用に関する情報は、本番環境での Compose の利用 を参照してください。

管理タスクの例

よく行われるもう 1 つの例は、Compose アプリにおけるサービスに対して、特別なタスクあるいは管理タスクを実行する場合です。 ここでは、データベースバックアップを実行する例を示します。

docker-compose.yml から始めます。

web:
  image: example/my_web_app:latest
  depends_on:
    - db

db:
  image: postgres:latest

docker-compose.admin.yml において、新しいサービスを追加して、データベースのエクスポートまたはバックアップを行うようにします。

    dbadmin:
      build: database_admin/
      depends_on:
        - db

通常の環境を起動するときはdocker-compose up -dを実行します。 またデータベースバックアップを実行するときは、docker-compose.admin.ymlも含めるようにして実行します。

$ docker-compose -f docker-compose.yml -f docker-compose.admin.yml \
  run dbadmin db-backup

サービスの拡張

メモ

キーワードextendsは、かつての Compose ファイルフォーマットバージョン 2.1 までにおいてサポートされます。 (バージョン 2 における extends を参照のこと。) これは Compose バージョン 3.x ではサポートされていません。 キーワードの追加、削除に関しては バージョン 3 のまとめアップグレード方法 を参照してください。 また moby/moby#31101 では、将来のバージョンにおいて何らかの形式でextendsをサポートする可能性について議論するスレッドがありますので、確認してみてください。 キーワードextendsは、docker-compose のバージョン 1.27 およびそれ以降から含まれるようになりました。

Docker Compose のextendsキーワードを使うと、さまざまな設定ファイルに共通する内容を共有することができます。 それはまったく別のプロジェクト間でも可能です。 ごく標準的な設定オプションを再利用しているサービスがいくつもある場合に、このサービス拡張機能を活用することができます。 extendsを使って標準的なサービスオプションを 1 箇所に定義しておけば、それをどこからでも参照することができます。

volumes_fromdepends_onは、extendsを利用したサービス間での共有はされません。 これらが例外となっているのは、気づかないうちに依存関係が発生してしまうことを避けるためです。 volumes_fromはいつもローカルな定義に利用するものです。 こうしているからこそ、そのときの設定ファイルを読めば、サービス間の依存関係がはっきりわかることになります。 ローカルに定義しておくのは、参照されている側のファイルに変更が加わっても、影響がなく済むことにもつながります。

extends によるサービス拡張設定の理解

docker-compose.yml内にサービスを定義するときには、どのようなサービスであっても、別のサービスを拡張するように宣言できます。 たとえば以下のとおりです。

services:
  web:
    extends:
      file: common-services.yml
      service: webapp

上の設定は Compose に対して、common-services.ymlファイル内に定義されているwebappサービスの設定を再利用することを指示しています。 common-services.ymlは以下のようになっているとします。

services:
  webapp:
    build: .
    ports:
      - "8000:8000"
    volumes:
      - "/data"

この例では、docker-compose.ymlファイル内のwebの直下に、buildportsvolumesの設定を行った場合と同じ結果を得ることができます。

さらにdocker-compose.yml内には、ローカルでの設定内容を定義あるいは再定義することができます。

services:
  web:
    extends:
      file: common-services.yml
      service: webapp
    environment:
      - DEBUG=1
    cpu_shares: 5

  important_web:
    extends: web
    cpu_shares: 10

また他のサービスを記述して、webサービスからそのサービスへリンクすることも可能です。

services:
  web:
    extends:
      file: common-services.yml
      service: webapp
    environment:
      - DEBUG=1
    cpu_shares: 5
    depends_on:
      - db
  db:
    image: postgres

利用例

複数のサービスを利用していてそこに共通設定が存在する場合に、単独のサービスを拡張することができるかもしれません。 以下の例では Compose アプリにおいて 2 つのサービスがあります。 ウェブアプリケーションとキューワーカー(queue worker)です。 この 2 つのサービスは同一のコードを用いるものであり、多くの設定オプションを共有します。

common.yml では共通する設定を定義します。

services:
  app:
    build: .
    environment:
      CONFIG_FILE_PATH: /code/config
      API_KEY: xxxyyy
    cpu_shares: 5

docker-compose.yml では、上の共通設定を利用する具体的なサービスを定義します。

services:
  webapp:
    extends:
      file: common.yml
      service: app
    command: /code/run_web_app
    ports:
      - 8080:8080
    depends_on:
      - queue
      - db

  queue_worker:
    extends:
      file: common.yml
      service: app
    command: /code/run_worker
    depends_on:
      - queue

設定の追加と上書き

Compose では、元からあったサービスの定義を、ローカルのサービス定義に向けてコピーします。 設定オプションが元々のサービスとローカルのサービスの両方にて定義されていた場合は、元のサービスの値はローカルの値によって 置き換えられるか、あるいは拡張されます

1 つの値しか持たないオプション、たとえばimagecommandmem_limitのようなものは、古い値が新しい値に置き換えられます。

元からのサービス

services:
  myservice:
    # ...
    command: python app.py

ローカル定義のサービス

services:
  myservice:
    # ...
    command: python otherapp.py

結果

services:
  myservice:
    # ...
    command: python otherapp.py

複数の値を持つオプションportsexposeexternal_linksdnsdns_searchtmpfsでは、両者の設定をつなぎ合わせます。

元からのサービス

services:
  myservice:
    # ...
    expose:
      - "3000"

ローカル定義のサービス

services:
  myservice:
    # ...
    expose:
      - "4000"
      - "5000"

結果

services:
  myservice:
    # ...
    expose:
      - "3000"
      - "4000"
      - "5000"

environmentlabelsvolumesdevicesの場合、Compose は設定内容を「マージ」して、ローカル定義の値が優先するようにします。

元からのサービス

services:
  myservice:
    # ...
    environment:
      - FOO=original
      - BAR=original

ローカル定義のサービス

services:
  myservice:
    # ...
    environment:
      - BAR=local
      - BAZ=local

結果

services:
  myservice:
    # ...
    environment:
      - FOO=original
      - BAR=local
      - BAZ=local

volumesdevicesの設定内容は、コンテナーのマウントパスを使ってマージされます。

元からのサービス

services:
  myservice:
    # ...
    volumes:
      - ./original:/foo
      - ./original:/bar

ローカル定義のサービス

services:
  myservice:
    # ...
    volumes:
      - ./local:/bar
      - ./local:/baz

結果

services:
  myservice:
    # ...
    volumes:
      - ./original:/foo
      - ./local:/bar
      - ./local:/baz

Compose ドキュメント

fig, composition, compose, docker, orchestration, documentation, docs