TL;DR
If you use ARG with a multi-stage build Dockerfile, be aware that the scope is closed inside the stage! Declare the ARG to use for each stage! Also, if the ARG used in multiple stages has a default value, define a global ARG and put the default value there!
It's okay if you make it like this!
Dockerfile
#If there is a default value for the ARG that is commonly used in each stage, define it before the first FROM.
ARG YOUR_ARG="Default value"
FROM alpine:latest as first_stage
#ARG must be declared for each stage used.
ARG YOUR_ARG
RUN echo "1st stage: ${YOUR_ARG}"
FROM alpine:latest as second_stage
#ARG must be declared for each stage used.
ARG YOUR_ARG
RUN echo "2nd stage: ${YOUR_ARG}"
In multi-stage builds, the scope of ARG and ENV seems to be limited per stage. Did you all know? I didn't know until I realized that I couldn't refer to the ARG value in the stage of the Dockerfile I made.
According to this comment
Correct, Dockerfile instructions, including ENV vars and ARG are scoped per build-stage, and will not be preserved in the next stage; this is by design. You can, however, set a global ARG (set before the first build-stage), and use that value in each build-stage; Dockerfile instructions, including ENV and ARG, are scoped for each build stage and will not be carried over to the next stage. This is what it is by design. However, if you use a global ARG (defined before the first build stage), you can take advantage of that value for each build stage.
... apparently ... Really?
It was also firmly listed in the Official Document.
The variable scope of an ARG instruction is until the end of the build stage in which it is defined. If you want to use ARG in multiple build stages, you need to specify the ARG instruction individually.
When I first read the document, I felt like I thought, "Ahhhhh, I completely understood it," without knowing the meaning of the build stage. .. ..
Let's actually see how ARG works in a multi-stage build.
At the time of writing this article, we have confirmed the operation with the following versions.
# docker --version
Docker version 18.09.1, build 4c52b90
Dockerfile
The Dockerfile used in this verification is as follows.
Dockerfile
#ARG1 declares globally and sets global default values.
ARG ARG1="arg1 global default value"
#ARG2 declares globally but does not set a global default value.
ARG ARG2
#ARG3 does not declare globally.
# ARG ARG3
FROM alpine:latest as first_stage
# first_In stage, each ARG is declared and the default value in scope is set.
ARG ARG1="arg1 first stage value"
ARG ARG2="arg2 first stage value"
ARG ARG3="arg3 first stage value"
RUN echo -e "first_stage:\n\tARG1=${ARG1}\n\tARG2=${ARG2}\n\tARG3=${ARG3}"
FROM alpine:latest as second_stage
# second_The stage declares each ARG but does not set a default value in scope.
ARG ARG1
ARG ARG2
ARG ARG3
RUN echo -e "second_stage:\n\tARG1=${ARG1}\n\tARG2=${ARG2}\n\tARG3=${ARG3}"
FROM alpine:latest as third_stage
# third_At stage, do not declare all ARGs.
# ARG ARG1
# ARG ARG2
# ARG ARG3
RUN echo -e "third_stage:\n\tARG1=${ARG1}\n\tARG2=${ARG2}\n\tARG3=${ARG3}"
Each ARG is set as follows.
ARG name | Settings |
---|---|
ARG1 | Set as a global ARG. Also specify the default value. |
ARG2 | Set as a global ARG. No default value is specified. |
ARG3 | Do not set as a global ARG. |
In addition, each stage is set as follows.
Stage name | Settings |
---|---|
first_stage | Declare each ARG. Set the default value in the stage. |
second_stage | Declare each ARG. Do not set default values in the stage. |
third_stage | Do not declare ARG. |
--build-arg
Build without specificationWhen building Docker Image, try building without specifying the value with --build-arg
.
# docker build . --no-cache
Sending build context to Docker daemon 14.85kB
...snip...
Step 7/14 : RUN echo -e "1st stage:\n\tARG1=${ARG1}\n\tARG2=${ARG2}\n\tARG3=${ARG3}"
---> Running in 2bbe78634ee8
first_stage:
ARG1=arg1 first stage value
ARG2=arg2 first stage value
ARG3=arg3 first stage value
...snip...
Step 12/14 : RUN echo -e "2nd stage:\n\tARG1=${ARG1}\n\tARG2=${ARG2}\n\tARG3=${ARG3}"
---> Running in 0c28af93ea9b
second_stage:
ARG1=arg1 global default value
ARG2=
ARG3=
...snip...
Step 14/14 : RUN echo -e "3rd stage:\n\tARG1=${ARG1}\n\tARG2=${ARG2}\n\tARG3=${ARG3}"
---> Running in cbca9ed88691
third_stage:
ARG1=
ARG2=
ARG3=
...snip...
--build-arg
Build with specificationNow try building with the value specified by --build-arg
.
# docker build --build-arg ARG1="build arg1 value" --build-arg ARG2="build arg2 value" --build-arg ARG3="build arg3 value" . --no-cache
Sending build context to Docker daemon 14.85kB
...snip...
Step 7/14 : RUN echo -e "1st stage:\n\tARG1=${ARG1}\n\tARG2=${ARG2}\n\tARG3=${ARG3}"
---> Running in 10b37c5a524b
first_stage:
ARG1=build arg1 value
ARG2=build arg2 value
ARG3=build arg3 value
...snip...
Step 12/14 : RUN echo -e "2nd stage:\n\tARG1=${ARG1}\n\tARG2=${ARG2}\n\tARG3=${ARG3}"
---> Running in e70e3ff9fe9b
second_stage:
ARG1=build arg1 value
ARG2=build arg2 value
ARG3=build arg3 value
...snip...
Step 14/14 : RUN echo -e "3rd stage:\n\tARG1=${ARG1}\n\tARG2=${ARG2}\n\tARG3=${ARG3}"
---> Running in e675e8f648e8
third_stage:
ARG1=
ARG2=
ARG3=
...snip...
--build-arg
. This is consistent with what is described in Official documentation ARG default values. The value specified by --build-arg
takes precedence over both the global default value and the in-stage default value.--build-arg
, it still doesn't seem to be available unless it is declared in that stage.--build-arg
[High priority]That's it.
This is a promotion of the project that triggered me to notice the behavior of ARG in multi-stage build.
Let's operate Minecraft's Bedrock Server easily! This is a project to the effect. Minecraft occasionally updates, but the client is mostly updated on its own, but Bedrock Server is not updated automatically, manually downloading the new version, unzipping the Zip file and extracting the binary file I had to replace it and restart the service ... or something. This project will update Bedrock Server automatically once you set it up! By the way, Docker is used to build Bedrock Server, so it doesn't pollute the environment!
Thank you!
Really done.
Recommended Posts