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
経由で自由に変更可能とするなども実現できます。