30
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

docker-compose コマンドでの args:, environment:, env_file: 及び .env ファイルの使い方

Posted at

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 で宣言した変数が追加・上書きされるよ
  • DockerfileENV 命令で宣言したものは、 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

./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

./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.ymlargs: で値は上書きされる
  • 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

./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

./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

./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

./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_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 を用意する。

./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 ファイルを用意する。

./variable-substitution-dotenv/.env
BUSYBOX_VERSION=latest

先程と同じ内容だが、 ./variable-substitution-dotenv/docker-compose.yml を用意する。

./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 を以下の内容に書き換える。

./variable-substitution-dotev/.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 builddocker-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 を実行すると以下となる。

./variable-substitution-dotenv/.env
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

./variable-substitution-dotenv-dockerfile-not-work/.env
BUSYBOX_VERSION="latest"

./variable-substitution-dotenv-dockerfile-not-work/Dockerfile

./variable-substitution-dotenv-dockerfile-not-work/Dockerfile
FROM busybox:${BUSYBOX_VERSION}

./variable-substitution-dotenv-dockerfile-not-work/docker-compose.yml

./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

./variable-substitution-dotenv-dockerfile-work/.env
BUSYBOX_VERSION="latest"

./variable-substitution-dotenv-dockerfile-work/Dockerfile

./variable-substitution-dotenv-dockerfile-work/Dockerfile
ARG BUSYBOX_VERSION
FROM busybox:${BUSYBOX_VERSION}

./variable-substitution-dotenv-dockerfile-work/docker-compose.yml

./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.ymlargs: 節で BUSYBOX_VERSION 変数を宣言
  • また、 docker-compose.ymlargs: 節で BUSYBOX_VERSION 変数宣言に対して、 .envBUSYBOX_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

./variable-substitution-dotenv-dockerfile-work-easy-to-read/.env
DOCKER_COMPOSER_BUSYBOX_VERSION="latest"

./variable-substitution-dotenv-dockerfile-work-easy-to-read/Dockerfile

./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

./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.ymlargs: 節で BUSYBOX_VERSION 変数を宣言
  • また、 docker-compose.ymlargs: 節で BUSYBOX_VERSION 変数宣言に対して、 .envDOCKER_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

.env
#...略...
DOCKER_COMPOSE_BUILD_TYPE="dev"
#...略...

ステージング用 .env

.env
#...略...
DOCKER_COMPOSE_BUILD_TYPE="dev"
#...略...

プロダクション用 .env

.env
#...略...
DOCKER_COMPOSE_BUILD_TYPE="prod"
#...略...

また、これらの .env は gitignore されており、リポジトリで管理されていないとします。

この状態で、 Dockerfiledocker-compose.yml を以下のように用意しておくことで、単一ソースコードを保ちながら、環境ごとの制御が可能となります。

Dockerfile

#...略...
ARG BUILD_TYPE="local"
#...略...
RUN yarn run ${BUILD_TYPE}
#...略...

docker-compose.yml

docker-compose.yml
#...略...
    build:
#...略...
      args:
        BUILD_TYPE: ${DOCKER_COMPOSE_BUILD_TYPE}
#...略...

他にも、 environment: を使って、各環境ごとのログの向き先やメールドライバの変更、 DB ドライバの変更なども可能です。

php を使った開発なら xdebug 有効無能の設定や、各種設定値を各個人の .env 経由で自由に変更可能とするなども実現できます。

30
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?