Dockerにおいて外部値を参照するユースケースについて整理する
目的
Dockerを使うときに混乱しがちな下記のユースケースについて実装例を交えて整理し、忘れたときにパッと思い出すためのメモです。
-
docker-compose.ymlに対し環境変数経由で値を渡したい -
Dockerfileに対し外部から値を渡したい - Dockerコンテナ内部に対し外部から値を渡したい
全体的に docker-composeを使ったDocker環境構築を想定しています。
下準備
動作を確認するためのDocker環境を用意します。
docker
┣ Dockerfile
┣ .env
┗ docker-compose.yml
version: '3'
services:
evntest:
FROM busybox
docker-compose.ymlに対し環境変数経由で値を渡したい
まずはdocker-compose.yml内で環境変数を使って動的に値を渡したい場合。
具体的には、サーバとしてコンテナを立ち上げてポート番号を環境ごとに変えたい場合や、後述のDockerfile内に環境変数を渡したい場合などが考えられます。
設定のポイントとしては
- 環境変数を設定すること(今回は.envに記載)
-
docker-compose.ymlにおいて、${DEV_PORT}の形式で環境変数を指定すること
ですね。
実装例
サーバの起動ポートを外部指定する場合を想定して、設定ファイルを下記のように変えます。
version: '3'
services:
evntest:
build:
context: ./
ports:
- '${DEV_PORT}:3000'
DEV_PORT=13000
ターミナルで docker-compose configを叩いてみます。
docker-compose config
services:
evntest:
build:
context: /home/vagrant/aws_learning
ports:
- published: 13000
target: 3000
version: '3'
ports.publishedが .envで設定された値になっていることが確認できました。
Dockerfileに対し外部から値を渡したい
docker-compose.ymlではなく、Dockerfile内で動的な値を使いたい場合。
具体的には、コンテナのビルドの過程でパラメータを動的に指定したい場合、例えばサーバの設定ファイルを環境ごとに切り替えたい、とかですかね。
設定のポイントとしては
-
docker-compose.ymlのbuild.argsに変数名=値の形式で変数を定義すること -
Dockerfileで利用したい変数をARG命令で定義すること
です。
docker-compose.yml内のbuild.argsで変数を宣言し、Dockerfile内のARGで変数をマッピングする、ということですね。
参照: https://docs.docker.com/compose/compose-file/compose-file-v3/#args
実装例
version: '3'
services:
evntest:
build:
context: ./
args:
- CONF=dev.conf
FROM busybox
ARG CONF
COPY $CONF /var/
CMD cat /var/dev.conf # コピー確認用
仮の設定ファイルを置いておく
dev conf
dockerをビルド/起動してみる
docker-compose build
docker-compose up
Recreating aws_learning_evntest_1 ... done
Attaching to aws_learning_evntest_1
evntest_1 | dev conf
aws_learning_evntest_1 exited with code 0
コンテナ内において catコマンドを実行することで中身を表示しています。問題なくファイルがコピーされていることが確認できます。
実装例(環境変数経由で値を渡す)
上の例では、docker-compose.ymlに直接変数を定義しましたが、値を環境変数経由で設定することも可能です。
version: '3'
services:
evntest:
build:
context: ./
args:
- CONF=${CONF}
CONF=dev.conf
これによって、.env → docker-compose.yml → Dockerfile に値が渡される形になっています。
Dockerコンテナ内部に対し外部から値を渡したい
今まではdocker-compose.ymlやDockerfileなどの設定ファイル内で環境変数を参照する方法について記載しましたが、今回は最終的にビルドされるコンテナ内で環境変数経由での値を設定したいケースについてです。
コンテナで変数を参照することはかんたんでいくつか方法があります。
いずれの方法も変数の中身がコンテナ内部でも維持されます。
-
Dockerfile内でENVで環境変数を定義する -
docker-compose.yml内でenvironmentを定義する - 外部ファイル内に環境変数を定義し、
docker-compose.yml内でenv_fileに外部ファイルを設定する。
参照:
- https://docs.docker.jp/engine/reference/builder.html#env
- https://docs.docker.jp/compose/environment-variables.html
実装例(Dockerfile内でENVを使って環境変数を定義する)
FROM busybox
ENV MODE local
CMD echo $MODE
dockerをビルド/起動してみる
docker-compose build
docker-compose up
Recreating aws_learning_evntest_1 ... done
Attaching to aws_learning_evntest_1
evntest_1 | local
ENVで設定された値がコンテナ内部でも保持されていることが確認できます。
実装例(docker-compose.yml内でenvironmentを定義する)
version: '3'
services:
evntest:
environment:
- MODE=local
build:
context: ./
実装例(docker-compose.yml内でenv_fileに外部ファイルを設定する)
MODE=local
version: '3'
services:
evntest:
env_file:
- .env_local
build:
context: ./
実装例(.env→docker-compose.yml→Dockerfile経由で環境変数をリレーする)
.env内に環境変数を定義し、それをdocker-compose.yml経由でDockerfileおよびコンテナに伝達するようなことも一応可能です。
あまり必要なケースはないかもしれませんが、docker-compose.ymlとDockerfileとで共通して外部変数を使いたい場合には使えるかもしれません。
MODE=local
version: '3'
services:
evntest:
build:
context: ./
args:
- MODE=${MODE}
FROM busybox
ARG MODE
ENV MODE $MODE
CMD echo $MODE
dockerをビルド/起動してみる
docker-compose build
docker-compose up
Recreating aws_learning_evntest_1 ... done
Attaching to aws_learning_evntest_1
evntest_1 | local
環境変数の値が問題なくコンテナ内で参照できていることが確認できます。
順番に考えると以下のような感じでしょうか。
-
.envの値がDockerにロードされてdocker-compose.ymlのbuild.argsに設定される -
ARG命令によって、Dockerfile内にbuild.argsの変数がマッピングされて使える状態になる -
ENV命令によってARG命令でマッピングされた変数が環境変数に設定され、コンテナ内で使えるようになる
まとめ
.env、env_file、env_file、ENVなど似たような名前の項目が多いので、焦っているときは特に混乱しがちです。
次焦ったときに役に立てばよいですね。
Discussion