48
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

updated at

Organization

docker-compose.ymlをDRYに書くテクニック2選

最近仕事で docker-compose.yml をメンテする機会が多く、その際に重宝したDRYに書くテクニック2つです。

Extension fields

Extension fields(公式ドキュメント)

compose fileのバージョン3.4以降から、Extension fieldsという機能が利用できるようになりました。
これは、YAMLのaliasとanchorの機能をdocker-compose.yml中でも利用できるようにしたものです。

使いどころ

  • 同じ環境変数を複数のコンテナに設定しなければならない
  • 複数コンテナで同じパスでマウントするvolumeがある

使用例

サンプルとして、大量の同じenvironmentを各コンテナで指定しなければならない例を見てみましょう。

適用前は次に示すように愚直に記述しています。

docker-compose.yml
---
version: '3.7'

services:
  nginx:
    image: nginx:alpine
    ports:
      - 80:80
    environment:
      ENV: development
      USER: user
      HOST: example.com
      HOGE: hoge
      FUGA: fuga
      FOO: foo
      BAR: bar

  rails:
    image: ruby:alpine
    environment:
      ENV: development
      USER: user
      HOST: example.com
      HOGE: hoge
      FUGA: fuga
      FOO: foo
      BAR: bar

これをExtension fieldsを使用して書くと次のように書けます。

---
version: '3.7'

x-environment: &environment
  ENV: development
  USER: user
  HOST: example.com
  HOGE: hoge
  FUGA: fuga
  FOO: foo
  BAR: bar

services:
  nginx:
    image: nginx:alpine
    ports:
      - 80:80
    environment: *environment

  rails:
    image: ruby:alpine
    environment: *environment

x-environment&environmentでaliasを設定し、*environmentで展開して利用しています。
このように書くことで、環境変数を変更する際、すべてのコンテナの記述を変更してまわらなくてもよくなります。

注意点

  • versionには3.4以降を指定する必要があります
  • トップレベルに記載する場合はキーをx-で始める必要があります

YAMLのalias、anchorは他にも記述方法がいくつかあります。
以下のサイトが参考になるかと思います。
https://tech-1natsu.hatenablog.com/entry/2018/12/16/004215

Multiple Compose files

Multiple Compose files(公式ドキュメント)

Multiple Compose filesはその名前の通り、複数のcomposeファイルを使う方法です。

通常、docker-composeコマンドを利用すると、カレントディレクトリ(存在しない場合は上位のディレクトリ)のdocker-compose.ymlが利用されます。
このファイルは、-fオプションかCOMPOSE_FILE環境変数で指定を変更することができます。

docker-compose.develop.ymlを使って、docker-compose up -dを行う場合は次のようになります。

# -fオプションの場合
docker-compose -f docker-compose.develop.yml up -d

# 環境変数の場青
COMPOSE_FILE=docker-compose.develop.yml docker-compose up -d
# or
export COMPOSE_FILE=docker-compose.develop.yml
docker-compose up -d

この-fオプションか環境変数COMPOSE_FILEに複数のdocker-compose用YAMLファイルを指定することで、マージされた内容が利用できます。これがMultiple Compose filesです。

使いどころ

  • 開発時は追加で起動するコンテナがある
  • 連携サービス用コンテナの有無や、環境変数などを自由に切り替えられるようにしたい

使用例

以下のような例を想定します。

  • nginxとrailsの2つのコンテナの環境
  • 開発時はnginx側で8080とホストの8080をバインドしたい
  • railsには開発時のみ、HOGE=hogeという環境変数を設定したい

普通にやろうとすると、docker-compose.ymlを2種作り、それぞれに似た内容を記述してしまい、DRYになりません。
Multiple Compose filesの機能を使いDRYに書くと、下記のように記述できます。

docker-compose.yml
---
version: '3.7'

services:
  nginx:
    image: nginx:alpine
    ports:
      - 80:80

  rails:
    image: ruby:alpine
development.yml
---
version: '3.7'

services:
  nginx:
    ports:
      - 8080:8080

  rails:
    environment:
      HOGE: hoge

development.ymlには、開発時のみに利用する設定を記述しています。

利用時は以下のように使います。

# 非開発時
docker-compose up -d

# 開発時
COMPOSE_FILE=docker-compose.yml:development.yml docker-compose up -d

このように設定することで、開発時にはdevelopment.ymlの内容とマージされた設定でコンテナが起動できます。

docker-compose configコマンドで最終的なYAMLを表示できるので、development.ymlを追加した場合の設定を見てみましょう。

COMPOSE_FILE=docker-compose.yml:development.yml dc config
# 以下が出力される
services:
  nginx:
    image: nginx:alpine
    ports:
    - published: 80
      target: 80
    - published: 8080
      target: 8080
  rails:
    environment:
      HOGE: hoge
    image: ruby:alpine
version: '3.7'

想定どおりになっていますね。

注意点

マージの挙動に関しては、下記のようになります。(詳細は公式ドキュメントを参照してください)

  • キーが無い場合:追加
  • キーがある場合:後で指定したファイルの内容で上書き
  • リストの場合:リストの要素を追加

docker-composeコマンドを利用するたびに設定するのは面倒なので、direnv等を使い、自動でCOMPOSE_FILE環境変数が設定されるようにすることをおすすめします。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
48
Help us understand the problem. What are the problem?