Dockerfileの"ENV"と"ARG"と"環境変数"について

docker

シェルの環境変数を Dockerfile 内で参照したい

シェルの環境変数を Dockerfile 内で使いたい、という状況がありました。
Dockerfile の公式ドキュメントで環境変数の項目を見ると、次のように書いてありました。

Dockerfile は環境変数( env 命令 で宣言)も解釈できます。命令文字(ステートメント・リテラル)中では、変数の様な構文でエスケープ・シーケンスも扱えます。
Dockerfile の中では、環境変数を $variable_name または ${variable_name} の形式で記述します。これらは同等に扱われます。固定用の構文として典型的に使われるのは、空白スペースを変数名に入れず ${foo}_bar のような変数名で割り当てることです。

正直何を言ってるのかよく分かりません。ドキュメント語って難しいですね。
とりあえず、環境変数は ${変数名} で使うことが出来るようです。

試してみます。環境変数の値を echo してみます。

何も出ません。
環境変数、と言っていますがシェルの環境変数とはまた違うものの様です。

ENV 命令

Dockerfile の環境変数についてさらに調べてみました。
環境変数操作のための命令としてENVが用意されており、公式ドキュメントによると

ENV 命令は、環境変数 と 値 のセットです。値は Dockerfile から派生する全てのコマンド環境で利用でき、 インラインで置き換え も可能です。

だそうです。この命令を用いて環境変数に値をセットするみたいですね。

そもそも、環境変数がちゃんと参照できているか確認するため、
先ほどの例をちょっと変えてみましょう。

Good-bye が出ました! 求めてたのと違います
Hello と出すことは出来ないのでしょうか?

ARG 命令

ARG 命令は、構築時に作業者が docker build コマンドで使う変数、 –build-arg = フラグを定義するものです。

どうやらこれを使うのが正解らしいです。
シェルの環境変数を渡すのではなく、 docker build コマンドの引数として値を渡すんですね。
(なんでこんな設計にしたのでしょう? Windowsなど非 Linux プラットフォームでの展開を考えるとこれが一番確実だったのでしょうか?)

ということで、ARG を用いてさっきの例を書き直してみました。

これで目出度く、Hello と出力されました。

ちなみに、以下のように書くとデフォルト値をセットできます。
これで、これまで通りに –build-arg 命令なしで実行しても動作させることが出来ます

まとめ

  • Dorkcerfile にシェルから変数を渡すには ARG 命令を用いる
  • Dockerfile の環境変数と シェルの環境変数は意味が異なる

docker