docker-compose コマンドでの args:, environment:, env_file: 及び .env ファイルの使い方
docker-compose v3 での、 args:, environment:, env_file: の使い方と .env ファイルの関係で迷子になることがあったので自分用に整理した。
まとめ
args: について
-
build 用変数だよ - なので、
run時は存在してないよ - 同じ変数を宣言した場合
docker-compose.yml > Dockerfileだよ -
docker-compose.ymlで宣言するとDockerfile内で宣言したのと同等になるよ
environment: について
- 環境変数を設定できるよ
-
run時にdocker-compose.ymlで宣言した変数が追加・上書きされるよ -
DockerfileのENV命令で宣言したものは、build時にARG命令の変数の様に使えてしまうので注意が必要だよ - かつ、
build時は、上述の様にdocker-compose.ymlで宣言した変数は渡っていないので注意が必要だよ
env_file: について
- ファイルから環境変数を追加する仕組みだよ
- 同名の環境変数が存在する場合の優先度は
environment: > env_file:だよ - 複数の
env_file:を指定した場合は、リストの後者の値で追加・上書きされるよ
.env について
-
docker-composeが利用する特殊なファイルが.envだよ - 変数置換機能を便利にしてくれるファイルが
.envだよ - (おそらく)
.envというファイル名を別名にして利用することは出来ないよ -
.envで宣言・定義した変数がdocker-compose.yml上で変数として利用できる仕組みだよ
※コードは https://github.com/hokutoasari/how-to-use-args-environment-env-file-dotenv-file-with-docker-compose に。
args: の使い方
まずは、公式ドキュメント。
Add build arguments, which are environment variables accessible only during the build process.
意訳: ビルド用の変数を設定できます。
ビルド用変数を設定できる仕組み。
※ environment variables が後述の environment: で指定する、所謂 環境変数 と紛らわしいので、ここでは ビルド用変数 と読み替えた。
ARG_VALUE1 - ARG_VALUE4 までを以下のように宣言・値設定して、振る舞いを確認します。
| Dockerfile | docker-compose.yml | |
|---|---|---|
| ARG_VALUE1 | arg1_in_Dockerfile | |
| ARG_VALUE2 | arg2_in_Dockerfile | arg2_in_yml |
| ARG_VALUE3 | arg3_in_yml | |
| ARG_VALUE4 |
./args/Dockerfile
FROM busybox
ARG ARG_VALUE1="arg1_in_Dockerfile."
ARG ARG_VALUE2="arg2_in_Dockerfile."
RUN echo "ARG_VALUE1 is ${ARG_VALUE1}" \
&& echo "ARG_VALUE2 is ${ARG_VALUE2}" \
&& echo "ARG_VALUE3 is ${ARG_VALUE3}" \
&& echo "ARG_VALUE4 is ${ARG_VALUE4}"
RUN echo "ARG_VALUE1 is $ARG_VALUE1" >> /tmp/outs.txt \
&& echo "ARG_VALUE2 is $ARG_VALUE2" >> /tmp/outs.txt \
&& echo "ARG_VALUE3 is $ARG_VALUE3" >> /tmp/outs.txt \
&& echo "ARG_VALUE4 is $ARG_VALUE4" >> /tmp/outs.txt
CMD cat /tmp/outs.txt \
&& echo "-----" \
&& echo "ARG_VALUE1 is ${ARG_VALUE1}" \
&& echo "ARG_VALUE2 is ${ARG_VALUE2}" \
&& echo "ARG_VALUE3 is ${ARG_VALUE3}" \
&& echo "ARG_VALUE4 is ${ARG_VALUE4}"
./args/docker-compose.yml
version: '3'
services:
with-args:
build:
context: ./
args:
ARG_VALUE2: "arg2_in_yml"
ARG_VALUE3: "arg3_in_yml"
実行。
% docker-compose build --no-cache && docker-compose up
...略...
Step 4/6 : RUN echo "ARG_VALUE1 is ${ARG_VALUE1}" && echo "ARG_VALUE2 is ${ARG_VALUE2}" && echo "ARG_VALUE3 is ${ARG_VALUE3}" && echo "ARG_VALUE4 is ${ARG_VALUE4}"
---> Running in 64893f52d5bc
ARG_VALUE1 is arg1_in_Dockerfile.
ARG_VALUE2 is arg2_in_yml
ARG_VALUE3 is
ARG_VALUE4 is
Removing intermediate container 64893f52d5bc
---> a66e7626d5eb
...略...
[Warning] One or more build-args [ARG_VALUE3] were not consumed
...略...
with-args_1 | ARG_VALUE1 is arg1_in_Dockerfile.
with-args_1 | ARG_VALUE2 is arg2_in_yml
with-args_1 | ARG_VALUE3 is
with-args_1 | ARG_VALUE4 is
with-args_1 | -----
with-args_1 | ARG_VALUE1 is
with-args_1 | ARG_VALUE2 is
with-args_1 | ARG_VALUE3 is
with-args_1 | ARG_VALUE4 is
args_with-args_1 exited with code 0
結果。
| Dockerfile | docker-compose.yml | build 時 | run 時 | |
|---|---|---|---|---|
| ARG_VALUE1 | arg1_in_Dockerfile | arg1_in_Dockerfile | ||
| ARG_VALUE2 | arg2_in_Dockerfile | arg2_in_yml | arg2_in_yml | |
| ARG_VALUE3 | arg3_in_yml | [Warning] | ||
| ARG_VALUE4 |
-
docker-compose.ymlのargs:で値は上書きされる -
docker-compose.ymlで宣言したargs:で未使用の変数があると Warning となる -
Dockerfileで利用しているが、docker-compose.ymlで宣言していない変数は警告などは無い - 当然ながら、
run時には利用できない
environment: の使い方
まずは、公式ドキュメント。
Add environment variables.
環境変数を追加できる仕組み。
前述の ビルド用変数 とは違い、こちらは所謂 環境変数 を設定する為の命令。
ENV_VALUE1 - ENV_VALUE4 までを以下のように宣言・値設定して、振る舞いを確認。
| Dockerfile | docker-compose.yml | |
|---|---|---|
| ENV_VALUE1 | env1_in_Dockerfile | |
| ENV_VALUE2 | env2_in_Dockerfile | env2_in_yml |
| ENV_VALUE3 | env3_in_yml | |
| ENV_VALUE4 |
./environment/Dockerfile
FROM busybox
ENV ENV_VALUE1="env1_in_Dockerfile."
ENV ENV_VALUE2="env2_in_Dockerfile."
RUN echo "ENV_VALUE1 is ${ENV_VALUE1}" \
&& echo "ENV_VALUE2 is ${ENV_VALUE2}" \
&& echo "ENV_VALUE3 is ${ENV_VALUE3}" \
&& echo "ENV_VALUE4 is ${ENV_VALUE4}" \
RUN echo "ENV_VALUE1 is $ENV_VALUE1" >> /tmp/outs.txt \
&& echo "ENV_VALUE2 is $ENV_VALUE2" >> /tmp/outs.txt \
&& echo "ENV_VALUE3 is $ENV_VALUE3" >> /tmp/outs.txt \
&& echo "ENV_VALUE4 is $ENV_VALUE4" >> /tmp/outs.txt
CMD cat /tmp/outs.txt \
&& echo "-----" \
&& echo "ENV_VALUE1 is ${ENV_VALUE1}" \
&& echo "ENV_VALUE2 is ${ENV_VALUE2}" \
&& echo "ENV_VALUE3 is ${ENV_VALUE3}" \
&& echo "ENV_VALUE4 is ${ENV_VALUE4}"
./environment/docker-compose.yml
version: '3'
services:
with-environment:
environment:
ENV_VALUE2: "env2_in_yml"
ENV_VALUE3: "env3_in_yml"
実行。
% docker-compose build --no-cache && docker-compose up
...略...
Step 4/6 : RUN echo "ENV_VALUE1 is ${ENV_VALUE1}" && echo "ENV_VALUE2 is ${ENV_VALUE2}" && echo "ENV_VALUE3 is ${ENV_VALUE3}" && echo "ENV_VALUE4 is ${ENV_VALUE4}"
---> Running in bb4ae383c1e7
ENV_VALUE1 is env1_in_Dockerfile.
ENV_VALUE2 is env2_in_Dockerfile.
ENV_VALUE3 is
ENV_VALUE4 is
Removing intermediate container bb4ae383c1e7
---> a01b51cd008a
...略...
with-environment_1 | ENV_VALUE1 is env1_in_Dockerfile.
with-environment_1 | ENV_VALUE2 is env2_in_Dockerfile.
with-environment_1 | ENV_VALUE3 is
with-environment_1 | ENV_VALUE4 is
with-environment_1 | -----
with-environment_1 | ENV_VALUE1 is env1_in_Dockerfile.
with-environment_1 | ENV_VALUE2 is env2_in_yml
with-environment_1 | ENV_VALUE3 is env3_in_yml
with-environment_1 | ENV_VALUE4 is
environment_with-environment_1 exited with code 0
結果。
| Dockerfile | docker-compose.yml | build 時 | run 時 | |
|---|---|---|---|---|
| ENV_VALUE1 | env1_in_Dockerfile | env1_in_Dockerfile | env1_in_Dockerfile | |
| ENV_VALUE2 | env2_in_Dockerfile | env2_in_yml | env2_in_Dockerfile | env2_in_yml |
| ENV_VALUE3 | env3_in_yml | env3_in_yml | ||
| ENV_VALUE4 |
-
build時は、Dockerfile記載の値が使われる -
run時に、docker-compose.ymlに設定した値が渡され上書きされる -
ENV命令及びenvironment:あくまで、環境変数をセットするものであることを意識して使うこと -
build時にENV命令で用意した値をビルド用変数的に使えてしまうので、注意すること
env_file: の使い方
まずは、公式ドキュメント。
Add environment variables from a file.
所謂 環境変数 を"ファイル"から追加する仕組み。
ENV_VALUE1 - ENV_VALUE5 までを以下のように宣言・値設定して、振る舞いを確認。
| Dockerfile | docker-compose.yml | some_env.env | |
|---|---|---|---|
| ENV_VALUE1 | env1_in_Dockerfile | ||
| ENV_VALUE2 | env2_in_Dockerfile | env2_in_yml | |
| ENV_VALUE3 | env3_in_yml | env3_in_file | |
| ENV_VALUE4 | env4_in_file | ||
| ENV_VALUE5 |
./env_file/Dockerfile
FROM busybox
ENV ENV_VALUE1="env1_in_Dockerfile."
ENV ENV_VALUE2="env2_in_Dockerfile."
RUN echo "ENV_VALUE1 is ${ENV_VALUE1}" \
&& echo "ENV_VALUE2 is ${ENV_VALUE2}" \
&& echo "ENV_VALUE3 is ${ENV_VALUE3}" \
&& echo "ENV_VALUE4 is ${ENV_VALUE4}" \
&& echo "ENV_VALUE5 is ${ENV_VALUE5}"
RUN echo "ENV_VALUE1 is $ENV_VALUE1" >> /tmp/outs.txt \
&& echo "ENV_VALUE2 is $ENV_VALUE2" >> /tmp/outs.txt \
&& echo "ENV_VALUE3 is $ENV_VALUE3" >> /tmp/outs.txt \
&& echo "ENV_VALUE4 is $ENV_VALUE4" >> /tmp/outs.txt \
&& echo "ENV_VALUE5 is $ENV_VALUE5" >> /tmp/outs.txt
CMD cat /tmp/outs.txt \
&& echo "-----" \
&& echo "ENV_VALUE1 is ${ENV_VALUE1}" \
&& echo "ENV_VALUE2 is ${ENV_VALUE2}" \
&& echo "ENV_VALUE3 is ${ENV_VALUE3}" \
&& echo "ENV_VALUE4 is ${ENV_VALUE4}" \
&& echo "ENV_VALUE5 is ${ENV_VALUE5}"
./env_file/docker-compose.yml
version: '3'
services:
with-env_file:
build:
context: ./
environment:
ENV_VALUE2: "env2_in_yml"
ENV_VALUE3: "env3_in_yml"
env_file:
- some_env.env
./env_file/some_env.env
ENV_VALUE3="env3_in_file"
ENV_VALUE4="env4_in_file"
実行。
% docker-compose build --no-cache && docker-compose up
...略...
Step 4/6 : RUN echo "ENV_VALUE1 is ${ENV_VALUE1}" && echo "ENV_VALUE2 is ${ENV_VALUE2}" && echo "ENV_VALUE3 is ${ENV_VALUE3}" && echo "ENV_VALUE4 is ${ENV_VALUE4}" && echo "ENV_VALUE5 is ${ENV_VALUE5}"
---> Running in 5851a9b3aa91
ENV_VALUE1 is env1_in_Dockerfile.
ENV_VALUE2 is env2_in_Dockerfile.
ENV_VALUE3 is
ENV_VALUE4 is
ENV_VALUE5 is
Removing intermediate container 5851a9b3aa91
---> 39f56354d7cd
...略...
with-env_file_1 | ENV_VALUE1 is env1_in_Dockerfile.
with-env_file_1 | ENV_VALUE2 is env2_in_Dockerfile.
with-env_file_1 | ENV_VALUE3 is
with-env_file_1 | ENV_VALUE4 is
with-env_file_1 | ENV_VALUE5 is
with-env_file_1 | -----
with-env_file_1 | ENV_VALUE1 is env1_in_Dockerfile.
with-env_file_1 | ENV_VALUE2 is env2_in_yml
with-env_file_1 | ENV_VALUE3 is env3_in_yml
with-env_file_1 | ENV_VALUE4 is env4_in_file
with-env_file_1 | ENV_VALUE5 is
env_file_with-env_file_1 exited with code 0
結果。
| Dockerfile | docker-compose.yml | some_env.env | build 時 | run 時 | |
|---|---|---|---|---|---|
| ENV_VALUE1 | env1_in_Dockerfile | env1_in_Dockerfile | env1_in_Dockerfile | ||
| ENV_VALUE2 | env2_in_Dockerfile | env2_in_yml | env2_in_Dockerfile | env2_in_yml | |
| ENV_VALUE3 | env3_in_yml | env3_in_file | env3_in_yml | ||
| ENV_VALUE4 | env4_in_file | env4_in_file | |||
| ENV_VALUE5 |
-
env_file:で指定した値よりもenvironment:の値が優先される -
env_file:で指定し、docker-compose.ymlで未設定の場合は、env_file:で指定した値が利用される - なお、実験はしてないが、ドキュメントにも記載がある通り、
env_file:に複数ファイルを指定すると、リストの後者の値で追加・上書きされる
.env ファイルの使い方
.env ファイルは、 docker-compose の中で特別に扱われるファイル。
変数置換機能にて利用される。
変数置換機能
.env ファイルは、 docker-compose の変数置換機能にて利用される為、まずは変数置換機能を試す。
公式ドキュメント。 https://docs.docker.com/compose/compose-file/#variable-substitution
Your configuration options can contain environment variables. Compose uses the variable values from the shell environment in which docker-compose is run.
意訳: docker-compose を実行するシェルの環境変数を docker-compose の変数として利用する事ができます。
以下の内容で ./variable-substitution/docker-compose.yml を用意する。
version: '3'
services:
variable-substitution:
image: busybox:${BUSYBOX_VERSION}
一時的に BUSYBOX_VERSION=latest という環境変数を設定しながら docker-compose up する。(build の必要が無いので、直接 up となる。)
% env BUSYBOX_VERSION="latest" docker-compose up
...略...
variable-substitution_variable-substitution_1 exited with code 0
無事に pull して up して終了した。
同様に、 BUSYBOX_VERSION=musl を環境変数に設定し、 docker-compose up する。
% env BUSYBOX_VERSION="musl" docker-compose up
...略...
variable-substitution_variable-substitution_1 exited with code 0
こちらも同様に無事に pull して up して終了した。
確認のため、 docker images で手元の image 一覧を確認する。
% docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
busybox musl 8bce8d24824c 5 weeks ago 1.47MB
busybox latest f0b02e9d092d 5 weeks ago 1.23MB
確かに、 latest, musl TAG が打たれた image が存在することを確認した。
docker-compose には、このように、シェルを実行する環境の環境変数を docker-compose に渡す仕組みがある。
これが、変数置換機能の1つ。
.env ファイル
公式ドキュメントには、以下とある。
You can set default values for environment variables using a .env file, which Compose automatically looks for. Values set in the shell environment override those set in the .env file.
意訳: docker-compose は、 .env ファイルを見つけると、デフォルトの環境変数を設定します。また、シェルの環境変数から設定された値は、 .env ファイルで設定された値で上書きされます。
以下のように、 ./variable-substitution-dotenv/.env ファイルを用意する。
BUSYBOX_VERSION=latest
先程と同じ内容だが、 ./variable-substitution-dotenv/docker-compose.yml を用意する。
version: '3'
services:
variable-substitution-dotenv:
image: busybox:${BUSYBOX_VERSION}
この状態で、今度は一時的な環境変数を設定せずに up してみる。
※事前に作成済みのコンテナを docker rm から削除、同様に pull 済みの images も docker rmi で削除しておくと動作がわかりやすいかも知れない。
% docker-compose up
Creating network "variable-substitution-dotenv_default" with the default driver
Pulling variable-substitution-dotenv (busybox:latest)...
latest: Pulling from library/busybox
9758c28807f2: Pull complete
Digest: sha256:a9286defaba7b3a519d585ba0e37d0b2cbee74ebfe590960b0b1d6a5e97d1e1d
Status: Downloaded newer image for busybox:latest
Creating variable-substitution-dotenv_variable-substitution-dotenv_1 ... done
Attaching to variable-substitution-dotenv_variable-substitution-dotenv_1
無事に、 latest が pull されて、 up したことがわかる。
続けて、 ./variable-substitution-dotenv/.env を以下の内容に書き換える。
BUSYBOX_VERSION=musl
この状態で、再度 docker-compose up してみる。
% docker-compose up
Pulling variable-substitution-dotenv (busybox:musl)...
musl: Pulling from library/busybox
7c3804618ebb: Pull complete
Digest: sha256:605de95bca536139f324abdecf88dcab492c8457346e7fc92e37dff6e263f341
Status: Downloaded newer image for busybox:musl
Recreating variable-substitution-dotenv_variable-substitution-dotenv_1 ... done
Attaching to variable-substitution-dotenv_variable-substitution-dotenv_1
variable-substitution-dotenv_variable-substitution-dotenv_1 exited with code 0
無事に、 musl が pull されて、 up したことがわかる。
このように、 .env ファイルを用いると、シェル実行環境の環境変数を汚染せずに、 docker-compose に変数を渡す事が可能となる。
ちなみに、公式ドキュメントには、以下の注意書きがある。
Note when using docker stack deploy
The .env file feature only works when you use the docker-compose up command and does not work with docker stack deploy.
意訳
ノート:
docker stack deployを使う方へ
.envファイルを用いた本機能は、docker-compose upコマンドのみ動作します。docker stack deployでは、動かないよ。
docker stack deploy 利用時の注意書きなので、 only works when you use the docker-compose up command と書いてるのだと思うが、実際は docker-compose up コマンドだけではなく、 dockre-compose コマンドに対して機能する。
具体的には、 docker-compose build や docker-compose config コマンドでも機能する。
試しに、現在の状態で docker-compose config を実行すると下記となる。(docker-compose config は、最終的に実行される yml を確認する為のコマンド。)
% docker-compose config
services:
variable-substitution:
image: busybox:musl
version: '3'
${BUSYBOX_VERSION} 部分が変数展開されて、 busybox:musl となっているのがわかる。
続けて、 ./variable-substitution-dotenv/.env を以下の内容に書き換えて docker-compose config を実行すると以下となる。
BUSYBOX_VERSION=latest
% docker-compose config
services:
variable-substitution:
image: busybox:latest
version: '3'
同様に ${BUSYBOX_VERSION} 部分が変数展開されて、 busybox:latest となっているのがわかる。
.env ファイルを用いることで docker-compose に変数が渡せる事が確認できた。
.env ファイルを用いた変数置換機能で勘違いしやすい点と対処法
なお、当然ながら、以下の .env, Dockerfile 及び docker-compose.yml の構成は build 出来ない。
./variable-substitution-dotenv-dockerfile-not-work/.env
BUSYBOX_VERSION="latest"
./variable-substitution-dotenv-dockerfile-not-work/Dockerfile
FROM busybox:${BUSYBOX_VERSION}
./variable-substitution-dotenv-dockerfile-not-work/docker-compose.yml
version: '3'
services:
variable-substitution-dotenv-dockerfile-not-work:
build:
context: ./
実行。
% docker-compose build --no-cache
Building variable-substitution-dotenv-dockerfile-not-work
Step 1/1 : FROM busybox:${BUSYBOX_VERSION}
ERROR: Service 'variable-substitution-dotenv-dockerfile-not-work' failed to build : invalid reference format
これまでの動作確認や公式ドキュメントを読めば当然なのだが、以下の状態となっている。
-
Dockerfileの冒頭で用いているbusybox:${BUSYBOX_VERSION}のBUSYBOX_VERSION変数はbuild 用変数としてDockerfileとして宣言されていない -
.envファイルを用いてdocker-composeに変数を渡す仕組みは、当然ながらdocker-composeまでしか値が渡らない - つまり、
Dockerfileまで変数が渡っていない
build できるようにするには、以下の構成とする必要がある。
./variable-substitution-dotenv-dockerfile-work/.env
BUSYBOX_VERSION="latest"
./variable-substitution-dotenv-dockerfile-work/Dockerfile
ARG BUSYBOX_VERSION
FROM busybox:${BUSYBOX_VERSION}
./variable-substitution-dotenv-dockerfile-work/docker-compose.yml
version: '3'
services:
variable-substitution-dotenv-dockerfile-work:
build:
context: ./
args:
BUSYBOX_VERSION: ${BUSYBOX_VERSION}
実行。
% docker-compose build --no-cache
Building variable-substitution-dotenv-dockerfile-work
Step 1/2 : ARG BUSYBOX_VERSION
Step 2/2 : FROM busybox:${BUSYBOX_VERSION}
latest: Pulling from library/busybox
9758c28807f2: Pull complete
Digest: sha256:a9286defaba7b3a519d585ba0e37d0b2cbee74ebfe590960b0b1d6a5e97d1e1d
Status: Downloaded newer image for busybox:latest
---> f0b02e9d092d
Successfully built f0b02e9d092d
Successfully tagged variable-substitution-dotenv-dockerfile-work_variable-substitution-dotenv-dockerfile-work:latest
-
DockerfileにてARG命令を使いBUSYBOX_VERSION変数を宣言 -
docker-compose.ymlのargs:節でBUSYBOX_VERSION変数を宣言 - また、
docker-compose.ymlのargs:節でBUSYBOX_VERSION変数宣言に対して、.envのBUSYBOX_VERSION変数を割り当て -
.envファイルにて、BUSYBOX_VERSION変数の値を設定
これで、 .env の中で定義した BUSYBOX_VERSION の値を変更することで、シェル実行環境の環境変数を汚染せずに値を変更できるようになる。
ただ、上記の例示だと、 BUSYBOX_VERSION という変数名が各所(.env, Dockerfile 及び docker-compose.yml)で用いられていて、少々わかりにくい。
もう少しわかりやすく明示的に書くと、 .env, Dockerfile 及び docker-compose.yml は以下となる。
./variable-substitution-dotenv-dockerfile-work-easy-to-read/.env
DOCKER_COMPOSER_BUSYBOX_VERSION="latest"
./variable-substitution-dotenv-dockerfile-work-easy-to-read/Dockerfile
ARG BUSYBOX_VERSION="latest"
FROM busybox:${BUSYBOX_VERSION}
./variable-substitution-dotenv-dockerfile-work-easy-to-read/docker-compose.yml
version: '3'
services:
variable-substitution-dotenv-dockerfile-work-easy-to-read:
build:
context: ./
args:
BUSYBOX_VERSION: ${DOCKER_COMPOSER_BUSYBOX_VERSION}
-
DockerfileにてARG命令を使いBUSYBOX_VERSION変数を宣言し、かつ、 docker-compose から値が渡されない場合はデフォルト値としてlatestを用いるように宣言 -
docker-compose.ymlのargs:節でBUSYBOX_VERSION変数を宣言 - また、
docker-compose.ymlのargs:節でBUSYBOX_VERSION変数宣言に対して、.envのDOCKER_COMPOSER_BUSYBOX_VERSION変数を割り当て -
.envファイルにて、DOCKER_COMPOSER_BUSYBOX_VERSION変数の値を設定
"変数"や"環境変数"という単語が多くなりややこしいので、具体的な変数名を見ると、何がどこに変数・値として受け継がれていくのかが分かると思う。
名称(ラベル)がややこしいだけで、 .env -> docker-compose.yml -> Dockerfile と、変数名と値を受け渡していく仕組みが分かる。
.env ファイルを用いた変数置換機能に関しては、(この表現が正しいか怪しいが...) .env ファイルを用いた変数置換機能は docker-compose.yml に変数と値を渡す仕組み と捉えるとわかりやすいかも知れない。
ちょっとした余談
実は、先に例示した以下の書き方はあまり推奨しません。
ARG BUSYBOX_VERSION="latest"
FROM busybox:${BUSYBOX_VERSION}
例えば、 github actions (等)の制約で、以下のようなケースが、ままあります。
Dockerfileファイル中の最初の命令はFROMでなければなりません。
そもそも FROM の TAG 値は、(開発|実行)環境の統一性を考えると "latest" すら使わずに、確実な値を使う方が望ましいと考えています。
もちろん、この限りじゃないケースもあると思いますが、 build のタイミングによっては不本意なメジャーバージョンアップが行われてしまうなどの問題があります。
活用例
例えば、 docker-compose build する際に、ローカル、ステージング、プロダクションなどの環境によって yarn run {script} の実行を制御するなどが実現できます。
ローカル、ステージング、プロダクション用のビルド環境が各々別で存在するとし、かつ、それぞれに .env ファイルも存在するとします。
ローカル用 .env
# ...略...
DOCKER_COMPOSE_BUILD_TYPE="dev"
# ...略...
ステージング用 .env
# ...略...
DOCKER_COMPOSE_BUILD_TYPE="dev"
# ...略...
プロダクション用 .env
# ...略...
DOCKER_COMPOSE_BUILD_TYPE="prod"
# ...略...
また、これらの .env は gitignore されており、リポジトリで管理されていないとします。
この状態で、 Dockerfile と docker-compose.yml を以下のように用意しておくことで、単一ソースコードを保ちながら、環境ごとの制御が可能となります。
Dockerfile
# ...略...
ARG BUILD_TYPE="local"
# ...略...
RUN yarn run ${BUILD_TYPE}
# ...略...
docker-compose.yml
# ...略...
build:
# ...略...
args:
BUILD_TYPE: ${DOCKER_COMPOSE_BUILD_TYPE}
# ...略...
他にも、 environment: を使って、各環境ごとのログの向き先やメールドライバの変更、 DB ドライバの変更なども可能です。
php を使った開発なら xdebug 有効無能の設定や、各種設定値を各個人の .env 経由で自由に変更可能とするなども実現できます。