これは、なにをしたくて書いたもの?
Docker Composeで、構成ファイルを複数使って上書きができることはなんとなく知っていたのですが、ちゃんと情報を追ったことが
なかったので、ちょっと見てみることにしました。
Docker Composeでの構成の上書き
ドキュメントとしては、以下が該当します。
Share Compose configurations between files and projects | Docker Documentation
複数のComposeのファイルを使うことで、アプリケーションを様々な環境やワークロードに合わせてカスタマイズできるという仕組みです。
Using multiple Compose files lets you to customize a Compose application for different environments or different workflows.
Share Compose configurations between files and projects / Multiple Compose files
デフォルトでは、docker-compose.ymlとオプションのdocker-compose.override.ymlが読み込まれると書かれています。
By default, Compose reads two files, a docker-compose.yml and an optional docker-compose.override.yml file.
docker-compose.ymlの方が、基本構成ですね。docker-compose.override.ymlで、基本構成を上書きすることになります。
サービスが両方のファイルで定義されている場合は、マージが行われるようです。
If a service is defined in both files, Compose merges the configurations using the rules described in Adding and overriding configuration.
マージのルールは、こちらに書かれています。
Share Compose configurations between files and projects / Adding and overriding configuration
複数の値を取る設定については、両方のファイルの内容を足し合わせたものになります。
environtmentとlabelは名前を考慮したマージが行われるようです。
単一の値の場合は、上書き用のファイルの内容が採用されます。
あと、今回の内容とは関係ないですが、ある構成ファイルの内容を拡張(というか共通化)もできるようです。
Share Compose configurations between files and projects / Extending services
今回は、上書きについて試してみます。
環境
今回の環境は、こちら。
Docker Engine。
$ docker version Client: Docker Engine - Community Version: 20.10.23 API version: 1.41 Go version: go1.18.10 Git commit: 7155243 Built: Thu Jan 19 17:45:08 2023 OS/Arch: linux/amd64 Context: default Experimental: true Server: Docker Engine - Community Engine: Version: 20.10.23 API version: 1.41 (minimum version 1.12) Go version: go1.18.10 Git commit: 6051f14 Built: Thu Jan 19 17:42:57 2023 OS/Arch: linux/amd64 Experimental: false containerd: Version: 1.6.15 GitCommit: 5b842e528e99d4d4c1686467debf2bd4b88ecd86 runc: Version: 1.1.4 GitCommit: v1.1.4-0-g5fd4c4d docker-init: Version: 0.19.0 GitCommit: de40ad0
Docker Compose。
$ docker compose version Docker Compose version v2.15.1
基本の構成ファイル
今回は、こちらのファイルを基本構成にします。
compose.yaml
services: proxy: image: nginx:1.23.3 volumes: - ./default.conf:/etc/nginx/conf.d/default.conf ports: - "80:80" deploy: resources: limits: cpus: '1' reservations: cpus: '1' webapp: image: quay.io/wildfly/wildfly:27.0.0.Final-jdk17 deploy: resources: limits: cpus: '1' reservations: cpus: '1'
ファイル名については、compose.yamlとするのが推奨のようなので、こちらに合わせます。
Compose specification / Compose file
WildFlyの前に、nginxをリバースプロキシとして置く構成にします。
default.conf
server { listen 80; listen [::]:80; server_name localhost; location / { proxy_pass http://webapp:8080/; } }
こちらで、動作確認しておきます。
$ docker compose up
ローカルにバインドされているポートの確認。
$ docker compose ps NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS configuration-override-proxy-1 nginx:1.23.3 "/docker-entrypoint.…" proxy 5 seconds ago Up 3 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp configuration-override-webapp-1 quay.io/wildfly/wildfly:27.0.0.Final-jdk17 "/opt/jboss/wildfly/…" webapp 5 seconds ago Up 3 seconds 8080/tcp
アクセス確認。
$ curl localhost
<!DOCTYPE html>
<html>
<head>
<!-- proper charset -->
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE8" />
<title>Welcome to WildFly</title>
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
<link rel="StyleSheet" href="wildfly.css" type="text/css">
</head>
<body>
<div class="wrapper">
<div class="content">
<div class="logo">
<img src="wildfly_logo.png" alt="WildFly" border="0" />
</div>
<h1>Welcome to WildFly</h1>
<h3>Your WildFly instance is running.</h3>
<p><a href="https://docs.wildfly.org">Documentation</a> | <a href="https://github.com/wildfly/quickstart">Quickstarts</a> | <a href="/console">Administration
Console</a> </p>
<p><a href="https://wildfly.org">WildFly Project</a> |
<a href="https://community.jboss.org/en/wildfly">User Forum</a> |
<a href="https://issues.jboss.org/browse/WFLY">Report an issue</a></p>
<p class="logos"><a href="https://www.jboss.org"><img src="jbosscommunity_logo_hori_white.png" alt="JBoss and JBoss Community" width=
"195" height="37" border="0"></a></p>
<p class="note">To replace this page simply deploy your own war with / as its context path.<br />
To disable it, remove the "welcome-content" handler for location / in the undertow subsystem.</p>
</div>
</div>
</body>
</html>
cpusに設定した値も確認しておきます。
$ docker container inspect configuration-override-proxy-1 | grep NanoCpus
"NanoCpus": 1000000000,
$ docker container inspect configuration-override-webapp-1 | grep NanoCpus
"NanoCpus": 1000000000,
このコンテナ群は、1度停止・削除しておきます。
上書きするファイルを用意する
上書きするファイルは、こちらを用意。
ドキュメントには、ファイル名がcompose.override.yamlでも読まれるとは書かれていませんが、いけるのでは?と思って試してみます。
compose.override.yaml
services: proxy: ports: - "10080:80" webapp: deploy: resources: limits: cpus: '2' reservations: cpus: '2'
nginxの方はローカルにバインドするポートを追加し、WildFlyの方はCPU割当を増やしています。
確認。docker compose upの時に、特に引数は指定しません。
$ docker compose up
nginxのコンテナに対して、ローカルにバインドされているポートが増えています。
$ docker compose ps NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS configuration-override-proxy-1 nginx:1.23.3 "/docker-entrypoint.…" proxy 46 seconds ago Up 44 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:10080->80/tcp, :::10080->80/tcp configuration-override-webapp-1 quay.io/wildfly/wildfly:27.0.0.Final-jdk17 "/opt/jboss/wildfly/…" webapp 46 seconds ago Up 44 seconds 8080/tcp
CPU割当は、WildFlyのコンテナのみ増えていますね。
$ docker container inspect configuration-override-proxy-1 | grep NanoCpus
"NanoCpus": 1000000000,
$ docker container inspect configuration-override-webapp-1 | grep NanoCpus
"NanoCpus": 2000000000,
というわけで、compose.override.yamlファイルで構成を上書きできていることが確認できました。
この時、compose.override.yamlファイルについてはなにも指定していないことがポイントです。
ちなみに、-fオプションでファイルを明示的に指定すると上書き用のファイルは読まれなくなります。
$ docker compose -f compose.yaml up
確認。
$ docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
configuration-override-proxy-1 nginx:1.23.3 "/docker-entrypoint.…" proxy About a minute ago Up About a minute 0.0.0.0:80->80/tcp, :::80->80/tcp
configuration-override-webapp-1 quay.io/wildfly/wildfly:27.0.0.Final-jdk17 "/opt/jboss/wildfly/…" webapp About a minute ago Up About a minute 8080/tcp
$ docker container inspect configuration-override-proxy-1 | grep NanoCpus
"NanoCpus": 1000000000,
$ docker container inspect configuration-override-webapp-1 | grep NanoCpus
"NanoCpus": 1000000000,
この場合は、それぞれのファイルを-fオプションで明示的に指定する必要があります。
$ docker compose -f compose.yaml -f compose.override.yaml up
これを利用することで、目的に応じて上書きするファイルを指定することが可能になります。
$ docker compose -f compose.yaml -f compose.prod.yaml up
また、オプションで指定するファイルの順番に上書きされていくようで、例えば以下のようにファイルの順番を逆にすると
$ docker compose -f compose.override.yaml -f compose.yaml up
マージされる値については結果は変わりませんが、単一の値については意味が変わってしまいます。
$ docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
configuration-override-proxy-1 nginx:1.23.3 "/docker-entrypoint.…" proxy 3 seconds ago Up 1 second 0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:10080->80/tcp, :::10080->80/tcp
configuration-override-webapp-1 quay.io/wildfly/wildfly:27.0.0.Final-jdk17 "/opt/jboss/wildfly/…" webapp 3 seconds ago Up 1 second 8080/tcp
$ docker container inspect configuration-override-proxy-1 | grep NanoCpus
"NanoCpus": 1000000000,
$ docker container inspect configuration-override-webapp-1 | grep NanoCpus
"NanoCpus": 1000000000,
使い方はわかりましたね。
デフォルトの上書き用ファイル名のパターンは?
ちょっと気になったので調べてみました。
GitHubリポジトリを見てみたのですが、今ひとつわからなかったので
GitHub - docker/compose: Define and run multi-container applications with Docker
straceで見てみることにしました。
$ strace -f docker compose up 2>&1
以下のようなファイルを対象とするようです。
[pid 39678] newfstatat(AT_FDCWD, "/path/to/compose.yaml", {st_mode=S_IFREG|0664, st_size=121, ...}, 0) = 0
[pid 39678] newfstatat(AT_FDCWD, "/path/to/compose.yml", 0xc00039b898, 0) = -1 ENOENT (そのようなファイルやディレクトリ
はありません)
[pid 39678] newfstatat(AT_FDCWD, "/path/to/docker-compose.yml", 0xc00039b968, 0) = -1 ENOENT (そのようなファイルやディレクトリはありません)
[pid 39678] newfstatat(AT_FDCWD, "/path/to/docker-compose.yaml", 0xc00039ba38, 0) = -1 ENOENT (そのようなファイルやディ
レクトリはありません)
[pid 39678] newfstatat(AT_FDCWD, "/path/to/compose.override.yml", 0xc00039bb08, 0) = -1 ENOENT (そのようなファイルやディレクトリはありません)
[pid 39678] newfstatat(AT_FDCWD, "/path/to/compose.override.yaml", {st_mode=S_IFREG|0664, st_size=46, ...}, 0) = 0
[pid 39678] newfstatat(AT_FDCWD, "/path/to/docker-compose.override.yml", 0xc00039bca8, 0) = -1 ENOENT (そのようなファイ
ルやディレクトリはありません)
[pid 39678] newfstatat(AT_FDCWD, "/path/to/docker-compose.override.yaml", 0xc00039bd78, 0) = -1 ENOENT (そのようなファイ
ルやディレクトリはありません)
compose.override.yml、compose.override.yaml、docker-compose.override.yml、docker-compose.override.yamlの4つですね。
まとめ
Docker Composeで、構成ファイルを複数使って定義内容を上書きしていみました。
なんとなくそんな機能があることは知っていたのですが、今回ちゃんとドキュメントと動きを確認して、どのような機能かハッキリしたので
良かったかなとは思います。
とはいえ、あんまり濫用する機能でもないかなとも思うので、利用はほどほどにといったところかなという印象を持ちました。