LoginSignup
10
10

More than 5 years have passed since last update.

Docker Compose - Compose の拡張サービス

Posted at

Docker Compose - Compose の拡張サービス

原文:Extending services in Compose
https://docs.docker.com/compose/extends/

Docker Compose の extends(拡張)キーワードによって、別々のファイルにある共通の設定を共有できるようにしたり、まったく別のプロジェクトでも使えるようになります。拡張サービス(Extending service)は、一般的に定義されたサービスを複数のサーバで再利用するときに便利です。1つの場所でサービスの定義をしておけば、extends を使うことで、どこからでも参照できます。

あるいは、複数の環境に、少しだけサービスが異なる(あるいは、いくつかの設定を変えている)同じアプリケーションをデプロイすることもできます。更に、コピー・ペーストを使わずに設定できます。

extends 設定の理解

サービスを docker-compose.yml で定義するとき、他のサービスの拡張を次のように宣言できます:

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

この命令によって、Compose は webapp サービスの定義にあたって common-services.yml ファイルの設定を再利用します。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

また、web サービスに別のサービスをリンクする記述もできます:

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

extends の使い方の詳細は、リファレンスをご参照ください。

使用例

この例はクイックスタートガイドのアプリケーションを再利用します(Compose に慣れていなければ、まずはクイックスタート・ガイドに取り組むことを推奨します)。例では、Compose をローカルの開発に使い、プロダクション環境へのデプロイを仮定していました。

ローカルとプロダクションの環境は似ていますが、いくつかの違いがあります。開発環境では、アプリケーション・コードを変更できるよう、ボリュームをマウントしていました。一方のプロダクションでは、外からみるコードは不変(イミュータブル)です。これは間違って変更しないように裏付けるものです。開発環境ではローカルの Redis コンテナを使いますが、プロダクションでは他のチームが管理する redis-production.example.com というサービスを使います。

この例の extends を設定するには、次のことが必要です:

  1. Docker イメージのウェブアプリケーションを Dockerfile で定義し、Compose サービスは common.yml で定義します。

  2. 開発環境を通常の Compose ファイル docker-compose.yml で定義します。

  • extends を使って webサービスを取得(pull)
  • コードを読み込めるボリュームを設定
  • アプリケーションがローカルで使うための追加 Redis サービスを作成

3.プロダクション環境を3つめの Compose ファイル production.yml で定義します。

  • extends を使って web サービスを取得(pull)
  • web サービスが外部のプロダクション Redis サービスに接続できるよう定義

web アプリケーションの定義

web アプリケーションの定義は次のようにします:

  1. ファイル app.py を作成します。

このファイルには、Flask を HTTP に使い、Redis カウンタを増やすという、簡単な Python アプリケーションを記述します。

from flask import Flask
from redis import Redis
import os


app = Flask(__name__)
redis = Redis(host=os.environ['REDIS_HOST'], port=6379)


@app.route('/')
def hello():
   redis.incr('hits')
   return 'Hello World! I have been seen %s times.\n' % redis.get('hits')


if __name__ == "__main__":
   app.run(host="0.0.0.0", debug=True)

このコードの環境変数 REDIS_HOST は、Redis の接続先を定義します。

2.requirements.txt ファイルに Python の依存関係を定義します:

flask
redis

3.アプリケーションが入っているイメージを構築する Dockerfile を作成します:

FROM python:2.7
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt
CMD python app.py

4.Compose の設定をする common.yml ファイルを作成します:

この設定は、どのようにアプリケーションを実行するか定義します。

web:
  build: .
  ports:
    - "5000:5000"

典型的なのは、この設定を docker-compose.yml に落とし込む方法ですが、複数のファイルで extends を使って読み込むためには、ファイルを分ける必要があります。

開発環境の定義

  1. ファイル docker-compose.yml ファイルを作成します。

extends オプションは、先の章で作成した common.yml から web サービスを取得します。

web:
  extends:
    file: common.yml
    service: web
  volumes:
    - .:/code
  links:
    - redis
  environment:
    - REDIS_HOST=redis
redis:
  image: redis

web サービスに新しく追加定義しているのは:

  • 外にある common.yml から web の基本設定を取得する。
  • 基本設定 common.yml の設定に volumeslinks を追加する。
  • 環境変数 REDIS_HOST に redis コンテナのリンク先を設定する。この環境では Docker Hub から radis イメージを取得して使う。

2.docker-compose up の実行。

Compose は web と redis コンテナの作成、リンク、起動を一緒に行います。アプリケーション・コードのある場所は、web コンテナの中にマウントします。

3.app.py のメッセージでコードがマウントされているか確認します。表示が Hello world! から Hello from Compose! になります。

変更を確認するには、ブラウザを再読み込みするのを忘れないでください!

プロダクション環境の定義

ほとんど完了していますが、次はプロダクション環境を定義します:

  1. ファイル production.yml を作成します。

docker-compose.yml と同じように、extends オプションは common.ymlweb サービスを取得します。

web:
  extends:
    file: common.yml
    service: web
  environment:
    - REDIS_HOST=redis-production.example.com

2.docker-compose -f production.yml up を実行します。

Compose は web コンテナだけ 作成し、REDIS_HOST 環境変数で設定された Redis へ接続します。この変数が指し示すのはプロダクションの Rails インスタンスです。

メモ:このウェブ・アプリケーションをブラウザで表示しようとしてもエラーになります。これは redis-production.example.com という Redis server が実在しないからです。

以上で、extends キーを使い、他の設定ファイルからサービスを同時に読み込めます。アプリケーションの開発時は、common.yml に web サービスが必要な変更を行えます。Compose は docker-compose 実行時、開発・プロダクション両方の環境で適切なものを選びます。これでもうコピー&ペーストしたり、手動で各々の環境を同期する必要はなくなります。

リファレンス

あらゆるサービスで、extends を他の設定キーと共に使えます。辞書に期待するように、 fileservice という2つのキーを常に必要とします。

file キーはどのファイルを読みにいくか指定します。絶対パスか相対パスで指定します。相対パスは、現在のファイルの場所からの相対パスです。

service キーは webdatabase のように、サービスを拡張する名前を指定します。

自分自身を他のものへ拡張することもできます。拡張の制限はありません。Compose は循環参照をサポートしないため、それらがあると docker-compose は処理を中断します。

設定の追加と上書き

Compose はローカルにオリジナルのサービス設定をコピーしますが、linksvolumes_from を除外します。これは現在のファイルを読み込むとき、サービス間の依存状況を明確にするためです。また、参照しているファイルが壊れて結果を返さなくても、これらをローカルで定義することもできます。

オリジナルのサービスとローカルのサービスで同じオプション設定が定義された場合は、ローカル値を "上書き" するか、オリジナル・サービスの定義を"拡張"(extend)します。この動作は他の設定オプションとは異なるものです。

imagecommandmem_limit のような1つしか値を持たないオプションは、新しい値が古い値を上書きします。これはデフォルトの振る舞いであり、例外全てを以下に記述します

# オリジナルのサービス
command: python app.py

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

# 結果
command: python otherapp.py

buildimage の場合、もしオリジナルのサービスが定義されていれば、Compose は他の設定を破棄します。

# オリジナルのサービス
build: .

# ローカルのサービス
image: redis

# 結果
image: redis

# オリジナルのサービス
image: redis

# ローカルのサービス
build: .

# 結果
build: .

portsexposeexternal_linksdnsdns_search複数のオプションを持つので、Compose はそれぞれの値を連結します。

# オリジナルのサービス
export:
  - "3000"

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

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

environmentlables の場合、Compose はローカルで定義された値を優先してマージ(統合)します。

# オリジナルのサービス
environment:
  - FOO=original
  - BAR=original

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

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

最後に volumedevices も、Compose はローカルで定義された値を優先してマージ(統合)します。

# オリジナルのサービス
volumes:
  - /original-dir/foo:/foo
  - /original-dir/bar:/bar

# ローカルのサービス
volumes:
  - /local-dir/bar:/bar
  - /local-dir/baz/:baz

# 結果
volumes:
  - /original-dir/foo:/foo
  - /local-dir/bar:/bar
  - /local-dir/baz/:baz
10
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
10