知らなかったので少しハマってしまったARGのお話しです.
結論
- 変数のスコープはビルドステージごとに保持される.
FROM
に変数を指定するには一番最初のFROM
より上で変数宣言する必要がある.- 一番最初の
FROM
より上で宣言された変数は,そのままビルドステージ内のスコープで利用できない.
検証
環境は
- macOS
- docker desktop community 2.3.0.3 stable
- docker engine 19.03.8
変数のスコープはビルドステージごとに保持される.
Dockerfileをこうする.
FROM alpine ARG OS=alpine RUN echo $OS FROM $OS RUN echo $OS
ビルドしてみる.
$ docker build --no-cache -t teru01/argtest:1.0 . Sending build context to Docker daemon 2.048kB Step 1/5 : FROM alpine ---> a24bb4013296 Step 2/5 : ARG OS=alpine ---> Running in 3fac749f761b Removing intermediate container 3fac749f761b ---> 99fd0ae09f82 Step 3/5 : RUN echo $OS ---> Running in 9dbb6a567f5c alpine Removing intermediate container 9dbb6a567f5c ---> 0edd0a618174 Step 4/5 : FROM $OS base name ($OS) should not be blank
Step 3/5では$OS
が出力されているが,2つ目のFROM
では$OS
が空なのでエラーになっている.
FROMに変数を指定するには一番最初のFROMより上で変数宣言する必要がある.
Dockerfileをこうする.先頭にARG
を置いた.
ARG OS=alpine FROM alpine FROM $OS RUN cat /etc/os-release
ビルドする.
$ docker build --no-cache -t teru01/argtest:1.1 . Sending build context to Docker daemon 2.048kB Step 1/4 : ARG OS=alpine Step 2/4 : FROM alpine ---> a24bb4013296 Step 3/4 : FROM $OS ---> a24bb4013296 Step 4/4 : RUN cat /etc/os-release ---> Running in b72e5e69ed0e NAME="Alpine Linux" ID=alpine VERSION_ID=3.12.0 PRETTY_NAME="Alpine Linux v3.12" HOME_URL="https://alpinelinux.org/" BUG_REPORT_URL="https://bugs.alpinelinux.org/" Removing intermediate container b72e5e69ed0e ---> aa58ec13c264 Successfully built aa58ec13c264 Successfully tagged teru01/argtest:1.1
Step3/4で$OS
が使われている.
一番最初のFROMより上で宣言された変数は,そのままビルドステージ内のスコープで利用できない.
Dockerfileを変更し,2つ目のステージ内でRUN
と$OS
を利用する.
ARG OS=alpine FROM alpine RUN echo $OS FROM $OS RUN echo $OS
$ docker build --no-cache -t teru01/argtest:1.2 . Sending build context to Docker daemon 2.048kB Step 1/5 : ARG OS=alpine Step 2/5 : FROM alpine ---> a24bb4013296 Step 3/5 : RUN echo $OS ---> Running in c09683cf6b8e Removing intermediate container c09683cf6b8e ---> fb642142e8aa Step 4/5 : FROM $OS ---> a24bb4013296 Step 5/5 : RUN echo $OS ---> Running in 998708ee2d3d Removing intermediate container 998708ee2d3d ---> 7589182a6cd2 Successfully built 7589182a6cd2 Successfully tagged teru01/argtest:1.2
Step3/5, 5/5で$OS
が空になってるのがわかる.一番最初のFROM
より上で宣言された変数は,プログラミング言語のグローバル変数と同じ挙動をするわけではないらしい.
一番最初のFROMより上のARGをスコープ内で使いたい時
そのスコープ内のARG
で宣言する.先ほどのDockerfileの例なら次のようになる.
ARG OS=alpine FROM alpine ARG OS RUN echo $OS FROM $OS RUN echo $OS
$ docker build --no-cache -t teru01/argtest:1.2 . Sending build context to Docker daemon 2.048kB Step 1/6 : ARG OS=alpine Step 2/6 : FROM alpine ---> a24bb4013296 Step 3/6 : ARG OS ---> Running in e5765868a2c5 Removing intermediate container e5765868a2c5 ---> 5c8dd4ab5b9e Step 4/6 : RUN echo $OS ---> Running in faee8bee7cf1 alpine Removing intermediate container faee8bee7cf1 ---> 5cb5c0e805b4 Step 5/6 : FROM $OS ---> a24bb4013296 Step 6/6 : RUN echo $OS ---> Running in c707c0304836 Removing intermediate container c707c0304836 ---> bd77da501ee5 Successfully built bd77da501ee5 Successfully tagged teru01/argtest:1.2
Step4/6で$OS
が使われ,スコープ内にARG
を使っていないStep6/6では依然として空のままになっている.