はじめに
docker-compose.yaml 内で環境変数を記述する際には、その展開時期に注意しましょう。
entrypoint や command フィールドに環境変数を記述する場合には、environment フィールドでの環境変数定義を参照できないため、別途工夫が必要です。
また、docker-compose up 実行時に、環境変数が「置換」される挙動については、使い方次第では不便な場合もあるため、注意が必要です。
問題点について、具体的なコードをあげて説明した後、対処法を紹介します。
検証環境
| |
docker-compose.yaml に環境変数 $VAR を記述した時の挙動
docker-compose.yaml には $VAR あるいは ${VAR} の形式で環境変数を記述できます。
環境変数の展開の挙動を確認しておきます。
以下のような docker-compose.yaml ファイルを用意します。
| |
YAML ファイルを配置しているディレクトリで、以下のコマンドを実行することで Docker Compose 内に記述されているイメージを使ってコンテナが立ち上がります。
| |
ここで、環境変数 X 、 Y を渡して起動してみます。
Z は docker-compose.yaml 内の environment フィールドで定義したものを参照してみます。
| |
コマンド実行直後のメッセージに Z 変数についてのメッセージが表示されています。
echo "$X",'$Y',"$Z" の処理を実行した結果、Z だけが出力されていないことからもわかりますが、環境変数は docker-compose up 実行タイミングで YAML ファイル内の各フィールド値の $AVR の記述が「置換」されているようです。
environment フィールドの値は、 YAML ファイルの「置換」のタイミングでは利用できません。
今回の YAML は起動直後に以下の内容と同じに扱われているということです。
| |
environment フィールドに設定した環境変数を entrypoint/command で参照する方法
それでは environment フィールドで設定した環境変数を entrypoint や command で参照するにはどうしたら良いでしょう?
環境変数を YAML ファイル解釈のタイミングではなく、 entrypoint 実行タイミングで展開させればよいことになります。
以下のように記述することでこれを実現できます。
| |
| |
無事、実行結果として hello.world,genzouw が出力されました。
$$Z についてですが、 docker-compose.yaml 内で $$VAR のように $ を二重に記述すると、環境変数の展開は行われず、 $VAR という文字列リテラルとして扱われます。
シェルの \$VAR のように解釈されたと思っていただければよいでしょう。
その後、 entrypoint に記述されたコマンドが実行されます。
$X と $Y は YAML ファイル読み込み直後にすでに環境変数が展開されているので、 以下のコマンドが実行されたのと同義です。
| |
結果として sh 実行時に $Z が無事展開されます。
entrypoint / command でプログラム、スクリプトを呼び出し、中で環境変数を参照する場合の注意
以下のような内容の main.sh を用意し、 entrypoint や command の中で main.sh を呼び出す場合には、今度は docker-compose コマンド実行時に指定した環境変数を利用できません。
| |
docker-compose.yaml は以下のとおりです。
| |
実行結果は以下のようになり、 $Z しか出力されません。
| |
この場合の対処は 2 つです。
1 つは docker-compose.yaml の environment フィールドに、コマンド実行時に設定された環境変数を引き継ぐ方法。
| |
実行します。
| |
もう1つは docker-compose up ではなく docker-compose run を使い、 -e オプションで環境変数を指定する方法。
| |
実行します。
| |
ひとこと
docker-compose up 実行時に $VAR が置換される挙動は、個人的には少し気持ちが悪いです。