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

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

  1. Compose ファイル全体を 複数の Compose ファイルの利用 により拡張します。

  2. 個々のサービスを extends フィールド を使って拡張します。

複数の 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
  links:
    - 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
  links:
    - db

db:
  image: postgres:latest

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

dbadmin:
  build: database_admin/
  links:
    - 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 までにおいてサポートされます。 (バージョン 1 における extendsバージョン 2 における extends を参照のこと。) これは Compose バージョン 3.x ではサポートされていません。 キーワードの追加、削除に関しては バージョン 3 のまとめアップグレード方法 を参照してください。 また moby/moby#31101 では、将来のバージョンにおいて、何らかの形式で extends をサポートする可能性について議論するスレッドがありますので、確認してみてください。

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

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

extends 設定の理解

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

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

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

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

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

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

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

important_web:
  extends: web
  cpu_shares: 10

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

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

利用例

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

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

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

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

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

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

設定の追加と上書き

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

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

# 元からのサービス
command: python app.py

# ローカル定義のサービス
command: python otherapp.py

# 結果
command: python otherapp.py

注釈

Compose ファイルバージョン 1 における buildimage

Compose ファイルフォーマットバージョン 1 における buildimage の 2 つについて、ローカル定義に一方を用いた場合に、他方が元々のサービスに定義されていたとすると、その他方のオプションは無視されます。

たとえば元のサービスに image: webapp が定義されていて、ローカルサービスでは build: . が定義されているとします。 このときの結果は build: . となり、image オプションはなくなります。

これはファイルフォーマットバージョン 1 においては、buildimage を同時に用いることができないためです。

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

# 元からのサービス
expose:
  - "3000"

# ローカル定義のサービス
expose:
  - "4000"
  - "5000"

# 結果
expose:
  - "3000"
  - "4000"
  - "5000"

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

# 元からのサービス
environment:
  - FOO=original
  - BAR=original

# ローカル定義のサービス
environment:
  - BAR=local
  - BAZ=local

# 結果
environment:
  - FOO=original
  - BAR=local
  - BAZ=local

Compose のドキュメント

参考

Share Compose configurations between files and projects

https://docs.docker.com/compose/extends/