知らんのか(枯れたネタ)
ということで、船井総研デジタルの Advent Calendar、2023/12/5 は @fsd-sayhorn がお届け!
結果だけ知りたい人は結論だけ読めば OK!
そう言えば、何気に Advent Calendar は初めて参加したかも。
これは何?
概要
みんな大好き Docker(誇張、あると思います)。
Docker では複数コンテナをまとめて扱える Compose という機能が提供されています。
Compose では制御するコンテナ群やその設定を YAML 形式のファイルで管理します。
たとえば、(Compose ファイルの中身は一旦置いておくとして)下記のような使い方をします。
docker compose -f my-compose.yml up
[+] Running 2/2
✔ ubuntu 1 layers [⣿] 0B/0B Pulled 6.8s
✔ f93f952dad40 Pull complete 3.9s
[+] Running 2/2
✔ Network qiita-20231205-dockercompose_default Create... 0.1s
✔ Container qiita-20231205-dockercompose-ubuntu-1 Cre... 0.2s
Attaching to qiita-20231205-dockercompose-ubuntu-1
qiita-20231205-dockercompose-ubuntu-1 | DISTRIB_ID=Ubuntu
qiita-20231205-dockercompose-ubuntu-1 | DISTRIB_RELEASE=23.04
qiita-20231205-dockercompose-ubuntu-1 | DISTRIB_CODENAME=lunar
qiita-20231205-dockercompose-ubuntu-1 | DISTRIB_DESCRIPTION="Ubuntu 23.04"
qiita-20231205-dockercompose-ubuntu-1 exited with code 0
my-compose.yml の中身が知りたい人はこちら
services:
ubuntu:
image: ubuntu:23.04
command: /bin/bash -c 'cat /etc/lsb-release'
cat /etc/lsb-release
はディストリビューションの情報を確認する手段の一つです。
他にも lsb_release
コマンドや cat /etc/os-release
を実行することでも確認できます。
ちなみに Linux カーネルのバージョンは uname -a
などとすると確認できます。
# WSL2 で動作する Ubuntu 22.04 で実行した結果
$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=22.04
DISTRIB_CODENAME=jammy
DISTRIB_DESCRIPTION="Ubuntu 22.04.3 LTS"
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 22.04.3 LTS
Release: 22.04
Codename: jammy
$ cat /etc/os-release
PRETTY_NAME="Ubuntu 22.04.3 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.3 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy
$ uname -a
Linux PC-M066 5.15.133.1-microsoft-standard-WSL2 #1 SMP Thu Oct 5 21:02:42 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
この使い方では、-f
オプションによって任意のファイル名を指定することができます。
今回は、このファイルを指定する際に複数のファイルを指定するとどうなるのか、ということがテーマです。
Compose には V1 と V2 があり、2023 年 7 月以降は V1 ではアップデートを受信しなくなりました。
現在では Compose V2 への移行が推奨されていますので、Migrate to Compose V2 を参考に移行しましょう。
コマンドフォーマットやデフォルトファイル名の変更なども含まれていますが、旧コマンド体系でも動作するなど互換性・利便性は考慮されているようです。
結論
複数の compose.yml ファイルが指定された場合、指定したファイルがマージされたかのように動作します。
たとえば、下記のようなファイルを想定した場合、ubuntu:22.04 イメージは pull されず、ubuntu:23.04 のイメージだけが pull されます。
(my-compose-second.yml で image が指定されているので、my-compose-first.yml で ubuntu:22.04 と指定されていた image が ubuntu:23.04 で上書きされる)
-
実行するコマンド(下記のいずれか)
-
docker compose -f my-compose-first.yml -f my-compose-second.yml up
-
COMPOSE_FILE=my-compose-first.yml:my-compose-second.yml docker compose up
-f
オプションやCOMPOSE_FILE
環境変数の指定順序が重要です。
前(左)に指定されたものから適用され、後(右)に書いたもので上書きされます。
-
-
使用するファイル
-
my-compose-first.yml
services: ubuntu: image: ubuntu:22.04 command: /bin/bash -c 'cat /etc/lsb-release'
-
my-compose-second.yml
services: ubuntu: image: ubuntu:23.04
-
解説・考察
前提(docker 環境)
$ docker version
Client: Docker Engine - Community
Version: 24.0.7
API version: 1.43
Go version: go1.20.10
Git commit: afdd53b
Built: Thu Oct 26 09:07:41 2023
OS/Arch: linux/amd64
Context: default
Server: Docker Engine - Community
Engine:
Version: 24.0.7
API version: 1.43 (minimum version 1.12)
Go version: go1.20.10
Git commit: 311b9ff
Built: Thu Oct 26 09:07:41 2023
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.6.25
GitCommit: d8f198a4ed8892c764191ef7b3b06d8a2eeb5c7f
runc:
Version: 1.1.10
GitCommit: v1.1.10-0-g18a0cb0
docker-init:
Version: 0.19.0
GitCommit: de40ad0
Compose ファイルを指定する機能について
Docker-docs-ja 24.0/docker compose によると、下記のような方法で Compose ファイルの指定が可能であり、また複数指定することができると書いてあります。
-
-f
オプション-f
フラグを使い、Compose 設定ファイルの場所を指定します。 -
COMPOSE_FILE
環境変数-f
、-p
、--profile
フラグを含む、様々な docker compose オプションを環境変数で指定できます。
COMPOSE_FILE
環境変数の設定は、-f
フラグを渡すのと同じです。COMPOSE_PROJECT_NAME
環境変数は、-p
フラグを渡すのと同じです。さらにCOMPOSE_PROFILES
環境変数は、--profile
フラグを渡すのと同じです。
フラグが明示的に指定される場合は、関連する環境変数は無視されます。 -
複数の Compose ファイルを指定
複数の
-f
設定ファイルを追加指定できます。複数のファイルを指定すると、 Compose が 1 つの設定の中にそれらを統合します。指定したファイル順の設定で、 Compose が構築します。後続のファイルは、事前の処理を上書き・追加します。
本機能を活用できそうなシチュエーション
本機能の特性(後から指定したファイルの内容で上書き・追加する)を考慮すると、たとえば次のような活用シチュエーションが考えられそうです。
- 環境別にコンテナを作り分ける
開発環境にはパケット解析ツールをインストールしたいが本番環境にはインストールしたくないなど、環境別で微妙に異なる差分が発生することはよくあると思います。
こうした場合、ベースとなる Compose ファイルを作成し、差分だけを記述した Compose ファイルを環境ごとに用意して適用することで実現できそうです。
ただし、この場合は共通のベースコンテナイメージを作成し、それを元に差分をビルドする方が適切なケースもあり得るので、検討が必要かもしれません。
他にも docker ホストの CPU アーキテクチャによって異なるコンテナを作りたいという場合もあるかもしれませんね。 - 他の人が作った Compose ファイルに影響を与えることなく自分専用のカスタマイズを追加する
誰かが作ったある環境に対して追加の設定やツールのインストール等を行いたいというニーズもまたよくあると思います。
こうした状況では、本機能を使わない場合には直接 Compose ファイルを書き換えたり、元の Compose ファイルのコピーを作成してそれを編集するなどすることになります。
しかし、そのようにしてしまうと二重管理になったり、問題が発生した時に切り分けるのが難しくなったりすることが考えられます。
本機能を使えば、元の Compose ファイルは編集しないのでこうした問題は発生しません。
実験
結論で示したファイルを用いる実験環境を構築し、実際に実行してみてどのような状況になるか観察してみます。
事前準備
下記のような構成となるようにワークスペース(ディレクトリ)を用意します。
なお、今回は dockerd
には特殊な指定はしていませんので、一般的な linux/amd64 環境を想定しています(筆者は Windows Subsystem for Linux 環境で実施しました)。
バージョン情報
項目 | バージョン |
---|---|
Windows Subsystem for Linux | 2.0.9.0 |
Ubuntu | 22.04.3 LTS |
docker(client) | 24.0.7 |
docker(server) | 24.0.7 |
Docker Compose | 2.21.0 |
ディレクトリ構成
$ pwd
/home/username/work/qiita-20231205-dockercompose
$ tree
.
├── my-compose-first.yml
└── my-compose-second.yml
0 directories, 2 files
(補足) tree コマンドについて
tree
コマンドがインストールされていない人は apt
などを使ってインストールすると同じことができます。
※tree
を使わなければいけない理由はないのでわざわざインストールしなくてもいいとは思いますが、お好みでどうぞ。
実験開始前のコンテナリソース状況(関係あるものだけ抜粋)
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
$ docker iamges -a
REPOSITORY TAG IMAGE ID CREATED SIZE
node 20.7.0-bullseye-slim a1c6dc3eddfa 2 months ago 253MB
(補足) node:20.7.0-bullseye-slim イメージについて
node:20.7.0-bullseye-slim
イメージがありますが、後の工程で必要なイメージだけ抽出するためにこのイメージの作成日をフィルタ条件として使用しています。
それ以外の用途はありませんので、このイメージは本実験とは本質的に無関係です。
フィルタの例)
docker images --filter "since=node:20.7.0-bullseye-slim"
実験結果
下記に示すとおり、-f
オプションの場合も COMPOSE_FILE
環境変数の場合も、Compose ファイルの指定順序に従って各ファイルの内容がマージされて実行されたような結果となりました。
仕様通り実装されていることが確認できたと言えるでしょう。
$ docker compose -f my-compose-first.yml -f my-compose-second.yml up
[+] Running 2/2
✔ ubuntu 1 layers [⣿] 0B/0B Pulled 7.1s
✔ 6360b3717211 Pull complete 2.7s
[+] Running 1/1
✔ Container qiita-20231205-dockercompose-ubuntu-1 Created 0.1s
Attaching to qiita-20231205-dockercompose-ubuntu-1
qiita-20231205-dockercompose-ubuntu-1 | DISTRIB_ID=Ubuntu
qiita-20231205-dockercompose-ubuntu-1 | DISTRIB_RELEASE=23.04
qiita-20231205-dockercompose-ubuntu-1 | DISTRIB_CODENAME=lunar
qiita-20231205-dockercompose-ubuntu-1 | DISTRIB_DESCRIPTION="Ubuntu 23.04"
qiita-20231205-dockercompose-ubuntu-1 exited with code 0
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
aefa7e06b022 ubuntu:23.04 "/bin/bash -c 'cat /…" 7 seconds ago Exited (0) 5 seconds ago qiita-20231205-dockercompose-ubuntu-1
$ docker images -a --filter "since=node:20.7.0-bullseye-silm"
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 23.04 f4cdeba72b99 4 days ago 70.3MB
$ docker compose -f my-compose-second.yml -f my-compose-first.yml up
[+] Running 2/2
✔ ubuntu 1 layers [⣿] 0B/0B Pulled 7.0s
✔ 5e8117c0bd28 Pull complete 2.8s
[+] Running 1/1
✔ Container qiita-20231205-dockercompose-ubuntu-1 Created 0.1s
Attaching to qiita-20231205-dockercompose-ubuntu-1
qiita-20231205-dockercompose-ubuntu-1 | DISTRIB_ID=Ubuntu
qiita-20231205-dockercompose-ubuntu-1 | DISTRIB_RELEASE=22.04
qiita-20231205-dockercompose-ubuntu-1 | DISTRIB_CODENAME=jammy
qiita-20231205-dockercompose-ubuntu-1 | DISTRIB_DESCRIPTION="Ubuntu 22.04.3 LTS"
qiita-20231205-dockercompose-ubuntu-1 exited with code 0
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
adfcfbd8db03 ubuntu:22.04 "/bin/bash -c 'cat /…" 10 seconds ago Exited (0) 10 seconds ago qiita-20231205-dockercompose-ubuntu-1
$ docker images -a --filter "since=node:20.7.0-bullseye-silm"
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 22.04 b6548eacb063 39 hours ago 77.8MB
$ COMPOSE_FILE=my-compose-first.yml:my-compose-second.yml docker compose up
[+] Running 2/2
✔ ubuntu 1 layers [⣿] 0B/0B Pulled 6.7s
✔ 6360b3717211 Pull complete 2.5s
[+] Running 1/1
✔ Container qiita-20231205-dockercompose-ubuntu-1 Created 0.1s
Attaching to qiita-20231205-dockercompose-ubuntu-1
qiita-20231205-dockercompose-ubuntu-1 | DISTRIB_ID=Ubuntu
qiita-20231205-dockercompose-ubuntu-1 | DISTRIB_RELEASE=23.04
qiita-20231205-dockercompose-ubuntu-1 | DISTRIB_CODENAME=lunar
qiita-20231205-dockercompose-ubuntu-1 | DISTRIB_DESCRIPTION="Ubuntu 23.04"
qiita-20231205-dockercompose-ubuntu-1 exited with code 0
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
104e117f1ca5 ubuntu:23.04 "/bin/bash -c 'cat /…" 7 seconds ago Exited (0) 6 seconds ago qiita-20231205-dockercompose-ubuntu-1
$ docker images -a --filter "since=node:20.7.0-bullseye-silm"
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 23.04 f4cdeba72b99 4 days ago 70.3MB
$ COMPOSE_FILE=my-compose-second.yml:my-compose-first.yml docker compose up
[+] Running 2/2
✔ ubuntu 1 layers [⣿] 0B/0B Pulled 7.0s
✔ 5e8117c0bd28 Pull complete 2.7s
[+] Running 1/1
✔ Container qiita-20231205-dockercompose-ubuntu-1 Created 0.1s
Attaching to qiita-20231205-dockercompose-ubuntu-1
qiita-20231205-dockercompose-ubuntu-1 | DISTRIB_ID=Ubuntu
qiita-20231205-dockercompose-ubuntu-1 | DISTRIB_RELEASE=22.04
qiita-20231205-dockercompose-ubuntu-1 | DISTRIB_CODENAME=jammy
qiita-20231205-dockercompose-ubuntu-1 | DISTRIB_DESCRIPTION="Ubuntu 22.04.3 LTS"
qiita-20231205-dockercompose-ubuntu-1 exited with code 0
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3d2b7aac45bf ubuntu:22.04 "/bin/bash -c 'cat /…" 7 seconds ago Exited (0) 6 seconds ago qiita-20231205-dockercompose-ubuntu-1
$ docker images -a --filter "since=node:20.7.0-bullseye-silm"
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 22.04 b6548eacb063 39 hours ago 77.8MB
まとめ
今回は Compose ファイルを複数指定できる機能について検証してみました。
Docker は結構実務でも活用していますが、Docker の仕様はプロダクトの進化に伴って増加していますのでまだまだ知らない機能がたくさんありそうです。
その内、--isolation
の動作なんかも深掘りしてみたいなと思っています。
では、年末・年度末進行の方々など、みなさま日々お忙しいとは思いますが、良きエンジニアライフをお過ごしください。