Docker のベスト プラクティス: Dockerfile での ARG と ENV の使用

Dockerを長期間使用してきた場合は、 Dockerfileの記述または少なくとも変更に慣れている可能性があります。 このファイルは、Docker イメージのレシピと考えることができます。これには、要素 (基本イメージ、パッケージ、ファイル) と命令 (イメージのビルドに役立つさまざまな RUNコマンド、 COPYその他のコマンド) の両方が含まれています。

ほとんどの場合、Dockerfile は一度書き込まれ、ほとんど変更されず、プロジェクトに関する何かが変更されない限り、そのまま使用されます。 これらのファイルは作成または変更される頻度が低いため、開発者は頻繁に使用される少数の命令 ( RUNCOPY最も EXPOSE 一般的) のみに依存する傾向があります。 その他の指示により、イメージを強化し、イメージの構成、管理、保守を容易にすることができます。 

この投稿では、とENVの説明について説明しARG、それらを使用する理由、方法、およびタイミングを探ります。

2400x1260 のベストプラクティス

ARG: ビルド時変数の定義

この ARG 命令では、ビルド段階ではアクセス可能になるが、イメージのビルド後は使用できなくなる変数を定義できます。 たとえば、このDockerfileを使用してイメージをビルドし、ビルドプロセス中に命令で指定された ARG 変数を使用可能にします。

FROM ubuntu:latest
ARG THEARG="foo"
RUN echo $THEARG
CMD ["env"]

ビルドを実行すると、出力に次の echo foo 行が表示されます。

$ docker build --no-cache -t argtest .
[+] Building 0.4s (6/6) FINISHED                                                                     docker:desktop-linux
<-- SNIP -->
 => CACHED [1/2] FROM docker.io/library/ubuntu:latest@sha256:8a37d68f4f73ebf3d4efafbcf66379bf3728902a8038616808f04e  0.0s
 => => resolve docker.io/library/ubuntu:latest@sha256:8a37d68f4f73ebf3d4efafbcf66379bf3728902a8038616808f04e34a9ab6  0.0s
 => [2/2] RUN echo foo                                                                                               0.1s
 => exporting to image                                                                                               0.0s
<-- SNIP -->

ただし、イメージを実行してコマンドの出力 env を調べると、次の情報は表示されません THEARG

$ docker run --rm argtest
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=d19f59677dcd
HOME=/root

ENV: ビルド変数とランタイム変数の定義

とは異なり ARG、この ENV コマンドでは、ビルド時と実行時の両方にアクセスできる変数を定義できます。

FROM ubuntu:latest
ENV THEENV="bar"
RUN echo $THEENV
CMD ["env"]

ビルドを実行すると、出力に次の echo bar 行が表示されます。

$ docker build -t envtest .
[+] Building 0.8s (7/7) FINISHED                                                                     docker:desktop-linux
<-- SNIP -->
 => CACHED [1/2] FROM docker.io/library/ubuntu:latest@sha256:8a37d68f4f73ebf3d4efafbcf66379bf3728902a8038616808f04e  0.0s
 => => resolve docker.io/library/ubuntu:latest@sha256:8a37d68f4f73ebf3d4efafbcf66379bf3728902a8038616808f04e34a9ab6  0.0s
 => [2/2] RUN echo bar                                                                                               0.1s
 => exporting to image                                                                                               0.0s
<-- SNIP -->

イメージを実行してコマンドの出力 env を調べると、予想どおり set が表示されます THEENV

$ docker run --rm envtest
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=f53f1d9712a9
THEENV=bar
HOME=/root

ARG のオーバーライド

命令の ARG より高度な使用法は、ビルド時に更新されるプレースホルダーとして機能することです。

FROM ubuntu:latest
ARG THEARG
RUN echo $THEARG
CMD ["env"]

イメージをビルドすると、次の値 $THEARGが不足していることがわかります。

$ docker build -t argtest .
<-- SNIP -->
 => CACHED [1/2] FROM docker.io/library/ubuntu:latest@sha256:8a37d68f4f73ebf3d4efafbcf66379bf3728902a8038616808f04e  0.0s
 => => resolve docker.io/library/ubuntu:latest@sha256:8a37d68f4f73ebf3d4efafbcf66379bf3728902a8038616808f04e34a9ab6  0.0s
 => [2/2] RUN echo $THEARG                                                                                           0.1s
 => exporting to image                                                                                               0.0s
 => => exporting layers                                                                                              0.0s
<-- SNIP -->

ただし、引数を使用して--build-argビルドコマンドラインでの値THEARGを渡すことができます。THEARG出力で が にfoo置き換えられていることがわかります。

 => CACHED [1/2] FROM docker.io/library/ubuntu:latest@sha256:8a37d68f4f73ebf3d4efafbcf66379bf3728902a8038616808f04e  0.0s
 => => resolve docker.io/library/ubuntu:latest@sha256:8a37d68f4f73ebf3d4efafbcf66379bf3728902a8038616808f04e34a9ab6  0.0s
 => [2/2] RUN echo foo                                                                                               0.1s
 => exporting to image                                                                                               0.0s
 => => exporting layers                                                                                              0.0s
<-- SNIP -->

Docker Compose ファイルでも、キーの下にあるbuildキーを使用してargs同じことを行うことができます。これらはマッピング ()THEARG: foo またはリスト ()- THEARG=foo として設定できることに注意してください。

services:
  argtest:
    build:
      context: .
      args:
        THEARG: foo

を実行すると docker compose up --build、出力で が THEARGfoo 置き換えられていることがわかります。

$ docker compose up --build
<-- SNIP -->
 => [argtest 1/2] FROM docker.io/library/ubuntu:latest@sha256:8a37d68f4f73ebf3d4efafbcf66379bf3728902a8038616808f04  0.0s
 => => resolve docker.io/library/ubuntu:latest@sha256:8a37d68f4f73ebf3d4efafbcf66379bf3728902a8038616808f04e34a9ab6  0.0s
 => CACHED [argtest 2/2] RUN echo foo                                                                                0.0s
 => [argtest] exporting to image                                                                                     0.0s
 => => exporting layers                                                                                              0.0s
<-- SNIP -->
Attaching to argtest-1
argtest-1  | PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
argtest-1  | HOSTNAME=d9a3789ac47a
argtest-1  | HOME=/root
argtest-1 exited with code 0

ENVの上書き

ビルド時にオーバーライド ENV することもできます。これは、 のオーバーライド方法と ARG は少し異なります。 たとえば、次の Dockerfile の例に示すように、命令に ENV 値がないキーを指定することはできません。

FROM ubuntu:latest
ENV THEENV
RUN echo $THEENV
CMD ["env"]

イメージをビルドしようとすると、次のエラーが表示されます。

$ docker build -t envtest .
[+] Building 0.0s (1/1) FINISHED                                                                     docker:desktop-linux
 => [internal] load build definition from Dockerfile                                                                 0.0s
 => => transferring dockerfile: 98B                                                                                  0.0s
Dockerfile:3
--------------------
   1 |     FROM ubuntu:latest
   2 |
   3 | >>> ENV THEENV
   4 |     RUN echo $THEENV
   5 |
--------------------
ERROR: failed to solve: ENV must have two arguments

ただし、Dockerfileから命令を削除する ENV ことはできます。

FROM ubuntu:latest
RUN echo $THEENV
CMD ["env"]

これにより、イメージをビルドできます。

$ docker build -t envtest .
<-- SNIP -->
 => [1/2] FROM docker.io/library/ubuntu:latest@sha256:8a37d68f4f73ebf3d4efafbcf66379bf3728902a8038616808f04e34a9ab6  0.0s
 => => resolve docker.io/library/ubuntu:latest@sha256:8a37d68f4f73ebf3d4efafbcf66379bf3728902a8038616808f04e34a9ab6  0.0s
 => CACHED [2/2] RUN echo $THEENV                                                                                    0.0s
 => exporting to image                                                                                               0.0s
 => => exporting layers                                                                                              0.0s
<-- SNIP -->

次に、フラグを使用して-eコマンドでdocker run環境変数を渡すことができます。

$ docker run --rm -e THEENV=bar envtest
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=638cf682d61f
THEENV=bar
HOME=/root

しかし、 .env ファイルは通常、Docker Compose に関連付けられていますが、 docker run.

$ cat .env
THEENV=bar

$ docker run --rm --env-file ./.env envtest
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=59efe1003811
THEENV=bar
HOME=/root

これは、キーを使用して environment Docker Compose を使用して行うこともできます。 値には変数形式を使用することに注意してください。

services:
  envtest:
    build:
      context: .
    environment:
      THEENV: ${THEENV}

THEENV値を指定しない場合、警告がスローされます。

$ docker compose up --build
WARN[0000] The "THEENV" variable is not set. Defaulting to a blank string.
<-- SNIP -->
 => [envtest 1/2] FROM docker.io/library/ubuntu:latest@sha256:8a37d68f4f73ebf3d4efafbcf66379bf3728902a8038616808f04  0.0s
 => => resolve docker.io/library/ubuntu:latest@sha256:8a37d68f4f73ebf3d4efafbcf66379bf3728902a8038616808f04e34a9ab6  0.0s
 => CACHED [envtest 2/2] RUN echo ${THEENV}                                                                          0.0s
 => [envtest] exporting to image                                                                                     0.0s
<-- SNIP -->
 ✔ Container dd-envtest-1    Recreated                                                                               0.1s
Attaching to envtest-1
envtest-1  | PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
envtest-1  | HOSTNAME=816d164dc067
envtest-1  | THEENV=
envtest-1  | HOME=/root
envtest-1 exited with code 0

変数の値は、次のようにいくつかの異なる方法で指定できます。

  • composeコマンドラインで、次の操作を行います。
$ THEENV=bar docker compose up

[+] Running 2/0
 ✔ Synchronized File Shares                                                                                          0.0s
 ✔ Container dd-envtest-1    Recreated                                                                               0.1s
Attaching to envtest-1
envtest-1  | PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
envtest-1  | HOSTNAME=20f67bb40c6a
envtest-1  | THEENV=bar
envtest-1  | HOME=/root
envtest-1 exited with code 0
  • ホスト・システムのシェル環境で、次の操作を行います。
$ export THEENV=bar
$ docker compose up

[+] Running 2/0
 ✔ Synchronized File Shares                                                                                          0.0s
 ✔ Container dd-envtest-1    Created                                                                                 0.0s
Attaching to envtest-1
envtest-1  | PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
envtest-1  | HOSTNAME=20f67bb40c6a
envtest-1  | THEENV=bar
envtest-1  | HOME=/root
envtest-1 exited with code 0
  • スペシャル.envでは ファイル:
$ cat .env
THEENV=bar

$ docker compose up

[+] Running 2/0
 ✔ Synchronized File Shares                                                                                          0.0s
 ✔ Container dd-envtest-1    Created                                                                                 0.0s
Attaching to envtest-1
envtest-1  | PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
envtest-1  | HOSTNAME=20f67bb40c6a
envtest-1  | THEENV=bar
envtest-1  | HOME=/root
envtest-1 exited with code 0

最後に、 を使用して docker compose runサービスを直接実行する場合は、フラグを使用して -e .env ファイル。

$ docker compose run -e THEENV=bar envtest

[+] Creating 1/0
 ✔ Synchronized File Shares                                                                                          0.0s
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=219e96494ddd
TERM=xterm
THEENV=bar
HOME=/root

tl;博士

ビルド プロセス中に変数にアクセスする必要があるが、実行時にはアクセスしない場合は、 ARG. ビルド中と実行時の両方、または実行時のみに変数にアクセスする必要がある場合は、 ENV.

どちらを選択するかについては、次のフローを考えてみます (図 1)。

ENVARG、 のdocker rundocker composeコマンドラインから上書きできます。これにより、変数を動的に更新し、柔軟なワークフローを構築できます。

さらに詳しく