Docker Composeの最適化:YAML AnchorsとMerge Keysで「コードの重複」を一掃する

Docker tutorial - IT technology blog
Docker tutorial - IT technology blog

Docker Composeにおける「コピペ」の悪夢

500行もあるdocker-compose.ymlを開いたものの、その80%が繰り返しのコードだったことはありませんか?DevOpsエンジニアなら、誰もが一度はこの光景に辟易したことがあるはずです。プロジェクトが数個のコンテナから複雑なマイクロサービスへと拡張されるにつれ、environmentnetworksloggingの記述を繰り返すことは、大きな負担となります。

例えば、10個のサービスで共通のログ設定を使用しているとしましょう。ログのサイズ制限を10MBから50MBに変更したいとき、10箇所すべてを修正しなければなりません。一箇所でも修正し忘れると、システム内で設定が不一致になってしまいます。ここで威力を発揮するのが、YAML Anchors (&)Merge Keys (<<:) です。これらを使えば、サードパーティ製ツールに頼ることなく、YAMLファイル内でスマートにコードを再利用できます。

クイックスタート:5分でComposeファイルを整理する

何度も同じことを書く代わりに、「テンプレート」を定義しましょう。以下の設定ファイルがどのように最適化されるか見てみましょう:

version: "3.9"

# 1. Extension Fields (x-で始まる) を使ってテンプレートを作成
x-common-setup: &common-config
  restart: always
  networks:
    - backend-network
  logging:
    driver: "json-file"
    options:
      max-size: "10m"
      max-file: "3"

services:
  web-api:
    # 2. Merge Key を使って設定を読み込む
    <<: *common-config
    image: my-api:latest
    ports:
      - "8080:8080"

  worker-process:
    <<: *common-config
    image: my-worker:latest
    environment:
      - NODE_ENV=production

networks:
  backend-network:
    driver: bridge

結果は驚くほどスッキリします。設定ファイルが非常に整理されました。もしログのmax-sizeを変更したくなったら、x-common-setup内の1行を修正するだけで済みます。

3つの重要要素:Anchors、Aliases、Merge Keysの解説

1. Anchor (&) – アンカー(目印)

&記号は、変数に名前を付けるようなものです。再利用したいデータブロックの直前に記述します(例:&my-config)。Dockerはこのブロックの内容を記憶し、後で呼び出せるようにします。

2. Alias (*) – エイリアス(呼び出し)

*記号は、保存した変数を呼び出す役割を果たします。*my-configと書くと、YAMLは宣言されたAnchorの内容をその場所にコピーすると解釈します。

3. Merge Key (<<:) – マージキー(設定の結合)

これが最も価値のある機能です。Alias(*)だけを使うと、キーの値が丸ごと置き換わってしまいます。しかし、<<:を使えば、Anchorの属性を現在のサービスにマージ(結合)できます。必要に応じて、独自の構成を追加したり、既存の値を上書きしたりすることも自由自在です。

services:
  auth-service:
    <<: *common-config # 共通設定を読み込む
    environment:
      - SERVICE_NAME=auth # 独自の環境変数を追加
    restart: on-failure # 'always' 属性を上書き

大規模マイクロサービスプロジェクト向けの高度なテクニック

実際の実務では、Anchorを1箇所にまとめるのではなく、用途別に細かく分けることが多いです。Extension Fieldsx-で始まるキー)を使うのが非常に有効なテクニックです。Docker Composeは実行時にこれらのキーを無視するため、理想的なテンプレート置き場になります。

x-env-base: &env-base
  environment:
    - DB_HOST=postgres
    - REDIS_URL=redis://cache:6379

x-deploy-limits: &deploy-limits
  deploy:
    resources:
      limits:
        cpus: '0.50'
        memory: 512M

services:
  payment-service:
    <<: [*env-base, *deploy-limits] # 複数のAnchorを同時にマージ
    image: payment:v1

複雑なYAMLファイルを扱っていると、デバッグが困難になることがあります。マージ結果が意図通りか確認するために、オンラインのデータフォーマットツールを使うのがおすすめです。例えば、ToolcraftのJSON Formatterに設定を貼り付けてみると、エラーの発見が早まります。この方法なら、コンテナを実際に起動しなくても、キーの上書きミスなどをすぐに特定できます。

ミスを避けるための3つの重要な注意点

  • 順序が非常に重要: Anchor(&)は、Alias(*)で呼び出す前に定義する必要があります。逆の順序で記述すると、Dockerは参照が見つからないというエラーを出します。
  • 配列(Arrays)の落とし穴: Merge Keyはキー・バリュー形式(マップ)では完璧に動作しますが、リスト(配列)の場合は追加ではなく「上書き」されます。Anchorに3つの環境変数があり、サービス側でもenvironmentを定義した場合、古いリストは完全に消えてしまいます。
  • 優先的に Docker Compose V2 を使用: YAMLの処理能力を最大限に活かすため、旧バージョンではなくdocker composeコマンドを使用するようにしましょう。

実戦経験からの結び

単純すぎるものにAnchorを乱用しないでください。ある属性が2回しか登場しない場合、Anchorを作ることでかえってファイルが読みづらくなる可能性があります。私は通常、ロギング設定、データベースの環境変数、あるいはリソース制限(CPU/RAM)などにこのテクニックを適用しています。プロフェッショナルなdocker-compose.ymlとは、繰り返しのコードの迷宮ではなく、システムの構造が明確に示されているファイルのことです。

Share: