Dockerビルド時にパラメータを与えたいときにDockerfileで定義し、–build-argオプションと合わせて使うARG。
それをどこに書くか考えたときに
- 最初に宣言されていたほうが読みやすい気もする
- それで不要なキャッシュミスが起こるとしたら嫌
と悩んだのでどういう仕様でどうすべきなのか調べてみました。
そもそも基本
ARGは書いた行以降で有効になります
↓なのでこういうのはエラーになります。
1 2 3 4 | FROM alpine RUN touch $foo ARG foo |
ARGとキャッシュ
公式ドキュメントには、
ARGが変わった場合、(定義ではなく)最初の使用の時にキャッシュミスが起こる。ただし全てのRUNはARGの値を環境変数として暗黙的に使っているのでキャッシュミスを起こす。
というようなことが書かれています。
実験
ARGを最初に宣言
まずARGを上のほうで定義して、–build-argを変更するとどうなるか見てみます。
Dockerfile
1 2 3 4 5 6 7 8 9 10 11 | FROM alpine ARG foo # ARGを使用しないしRUNでもない COPY hoge.txt hoge.txt # ARGを使用しないRUN RUN touch a.txt ## ARGを使用するRUN RUN touch ${foo}.txt |
これを–build-argを変えて2度ビルドしてみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # 1回目 $ docker build -t argtest --build-arg foo=foo . (ただの新規ビルドなので省略...) # 2回目 $ docker build -t argtest --build-arg foo=bar . Sending build context to Docker daemon 3.072kB Step 1/5 : FROM alpine ---> f70734b6a266 Step 2/5 : ARG foo ---> Using cache ---> 3745b7b0341c Step 3/5 : COPY hoge.txt hoge.txt # キャッシュ使用 ---> Using cache ---> 2d217e6c362f Step 4/5 : RUN touch a.txt # キャッシュミス ---> Running in 60bbfe069aed Removing intermediate container 60bbfe069aed ---> 37d7272ba87a Step 5/5 : RUN touch ${foo}.txt ---> Running in e5e45a313f73 Removing intermediate container e5e45a313f73 ---> 96c05a7eef27 Successfully built 96c05a7eef27 Successfully tagged argtest:latest |
ドキュメント通り、ARGを使っていないRUNでもキャッシュが使われていませんね。
ARGを使用する直前で宣言
ARGをそれを使用するRUNの直前に変えてみます。
Dockerfile
1 2 3 4 5 6 7 8 9 10 11 | FROM alpine # ARGを使用しないしRUNでもない COPY hoge.txt hoge.txt # ARGを使用しないRUN RUN touch a.txt # 使用する直前で定義 ARG foo ## ARGを使用するRUN RUN touch ${foo}.txt |
ビルド
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | # 1回目 $ docker build -t argtest --build-arg foo=foo . (省略...) # 2回目 $ docker build -t argtest --build-arg foo=bar . Sending build context to Docker daemon 3.072kB Step 1/5 : FROM alpine ---> f70734b6a266 Step 2/5 : COPY hoge.txt hoge.txt ---> Using cache ---> 22abac6ef40c Step 3/5 : RUN touch a.txt ## キャッシュ使用 ---> Using cache ---> 76402ca8ed9a Step 4/5 : ARG foo ---> Using cache ---> 723ae15aa137 Step 5/5 : RUN touch ${foo}.txt # ここでキャッシュミス ---> Running in 46f333bda19d Removing intermediate container 46f333bda19d ---> f0f795e9e70e Successfully built f0f795e9e70e Successfully tagged argtest:latest |
最初の例ではキャッシュミスになっていたRUN touch a.txtがUsing cacheになっています。
結論
ARGを直接使わないRUNにもキャッシュミスを起こすので、ARGは使用するRUNの直前で書いたほうが良い。