YAML include
等と検索した所、
RubyやPython等の独自仕様が山ほど出てきて死んだので備忘録として書き残す。
結論
- V2まで:
extends
を利用する - V3以降:
docker-compose.override.yml
をdocker-compose.yml
と同じディレクトリに配置するとマージしてくれる
どちらも後述で紹介しているので、
やり方だけ知りたい方はそちらを参照。
前提: そもそもYAMLで外部ファイルを参照する仕様はない
YAMLはデータをシリアライズ(文字列化)した文書ファイルでしかない。
外部ファイルを参照したければ、自前のプログラミング言語等で勝手に実装する必要がある。
例えばPHPのSymfonyというフレームワークでは、
YAMLファイルの上部にimports
というおまじないを記載することで外部ファイルを読み込んでYAMLファイル同士をマージして扱う事が可能となる。
参考記事: How to Import Configuration Files/Resources - Symfony Docs
これはYAMLファイルとしてはimports
という文字列の配列を定義しただけ。
これを読み取ったSymfonyが勝手に別のYAMLファイルも読み込みマージ、
巨大な連想配列を生成し直して、そこから自身のフレームワークの挙動を制御しているだけの話だ。
なので他の言語やライブラリでSymfonyと同じやり方を試してもうまくいかないだろう。
もしそのツールやライブラリの開発者が必要と判断したのなら、
独自の外部ファイル参照の仕組みが実装されることになる。
(その開発者が前例のSymfonyを元に同じような仕組みを採用するケースはあるかもしれないが期待薄)
例えばDockerのdocker-compose.ymlで外部ファイル参照がしたければ、
YAML 外部ファイル
といったワードで検索しても時間の無駄。
docker-compose.yml 外部ファイル
という風にツールやフレームワーク等を意識したワードとセットにして検索してみよう。
docker-compose.ymlで外部ファイルを参照する方法(V2まで)
※以下の方法はV2までのファイルフォーマットであり、
V3からは「フラットな構築にしなさい」というありがたいお言葉と共に取り除かれてしまった。
公式サイト: サービスの拡張 - Docker Compose
Docker Compose の
extends
(拡張)キーワードは、異なったファイル間で設定を共有できるだけでなく、異なったプロジェクトでも利用可能です。拡張サービスは複数のサービスを持っている場合、一般的な設定オプションの再利用に便利です。extends
を使えば、1箇所だけでなく、どこでも利用可能なサービス・オプションの共通セットを定義できます。
docker-compose.yml
extendsキーで外部ファイルを指定し、サービス名をキーにまるごとテンプレートとしてまるごと持ってくる。
その後、コンテナの用途に合わせてプロパティを上書き指定していく形になる。
web:
extends:
file: common-services.yml
service: webapp
ports:
- "4000:8080"
common-services.yml
webapp:
build: .
ports:
- "8000:8000"
volumes:
- "/data"
本題: V3でextendsが取り除かれた話
アップグレードガイドを確認した所、こんな風に書いてある。
extends
: This option has been removed forversion: "3.x"
Compose files. (For more information, see Extending services.)
和訳: このオプションはバージョン: 3.x
では削除されています。
実際にV3で使おうと思ったら、こんなエラーが出まくりで動く気配がない。
$ docker-compose ps
ERROR: The Compose file './docker-compose.yml' is invalid because:
Unsupported config option for services.db: 'extends'
この機能を一時的にONにしようとdocker-compose.ymlの先頭行をservice: "2"
に変更しても、
参照先のファイルがV3準拠の場合は「お前V3のdocker-composeを参照しようとしてるだろ!小手先の事をしてもダメだぞ!」と叱られてしまう。
「V3で無くなったextendsに関しては復活の可能性を議論しています」みたいなIssueを見つけた。
Add support for extends feature in Compose v3 / docker stack deploy #31101
ざっとIssueを流し読みしたところ、
extendsはそもそもバギーだし、依存関係含めると中々対応が難しいという問題があった。
それでV3で削除してフラットなデータ構造にしてねという対応にしたらしい。
当然非難轟々で「受け皿がない」「コピペだらけになるだろ」「もうdocker-compose.ymlを自動生成するスクリプト作ったわ」という感じで荒れに荒れている。
因みにV3に於けるextendsを公式のドキュメントで調べると、
「削除されました」というワードにたどり着くだけで散々たらい回しにされてしまう。
これに関しても利用者はブチ切れており、下記のお叱りのコメントが付いている。
Not only this, but the changelog says "this has been removed, see 'how to upgrade' for details". I look at "how to upgrade" for, you know, details on how to upgrade, and what that says is "see 'extending services' for details". I go to "extending services" figuring I'll finally see a way to extend my files, only to see "this has been removed, see the changelog for details".
At this point, this seems like a cruel joke the documentation writer is playing.
意訳: V2からのアップデートに追従するにはAをご覧ください、Aに行くとBをご覧ください、そして最後にはAをご覧くださいに戻る。こんな下らん言葉遊びをドキュメントに書くな。
DockerComposeの拡張フィールドを使う案が2018/8に出ているが、これは本格的な実装はまだまだ先っぽい?
完全にextendsと同じことがやりたいなら、docker-compose.ymlファイルを全てV2相当まで落とすか、
自分でスクリプトを作って自動的に生成する手段を取るしかなさそう。
追記: V3でもMultiple Compose filesを使う事で代用可能
extendsはなくても代用はできそうだ。
Multiple Compose filesに関しての記載がある記事を見つけたので追記。
参考記事: docker-compose.ymlをDRYに書くテクニック2選 - @reireias
この「Multiple Compose files」セクションがとても参考になる。
docker-composeは「docker-compose.override.yml」ファイルを用意したり、
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
などと記述することで複数のYAMLファイルをマージしながら起動出来る仕組みが存在するようだ。
ベースとなるdocker-compose.ymlは上書き上等レベルのシンプルさで記述しておき、
Makefileやshell-script、package.jsonなんかに書いて管理するというのがベストプラクティスになるだろう。
ただしYAMLファイル同士全体のマージが前提となる。
V2が出来ていたextendsみたいに、あちこちのファイルから少しずつついばむような指定は出来ない。
そこが少々不便ではあるものの、
docker-compose.yml
はシンプルにしましょうねって事を心がければ
その違いが大きな問題になることはほとんど無いと思う。