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