loading...

Docker – The ARG instruction

How to Create a Droplet with DigitalOcean

Sometimes when building Docker images, you may need to use variable data to customize the build. The ARG instruction is the tool to handle that situation. To use it, you add ARG instructions to your Dockerfile, and then when you execute the build command, you pass in the variable data with a --build-arg parameter. The --build-arg parameter uses the now familiar key-value pair format:

# The ARG instruction syntax
ARG <varname>[=<default value>]

# The build-arg parameter syntax
docker image build --build-arg <varname>[=<value>] ...

You can use multiple ARG instructions in your Dockerfile with corresponding --build-arg parameters on the docker image build commands. You have to include an ARG instruction for every use of the --build-arg parameter. Without the ARG instruction, the --build-arg parameter will not be set during the build, and you will get a warning message. If you do not provide a --build-arg parameter or you do not provide the value part of the key-value pair for a --build-arg parameter for an existing ARG instruction, and that ARG instruction includes a default value, then the variable will be assigned the default value.

Be aware that during the image build, even though --build-arg is included as a parameter of the docker image build command, the corresponding variable does not get set until the ARG instruction is reached in the Dockerfile. Said another way, the value of the key-value pair of a --build-arg parameter will never be set until after its corresponding ARG line in the Dockerfile.

The parameters defined in ARG instructions do not persist into containers run from the created image, however, ARG instructions create new zero-byte-sized layers in the resulting images. Here is an educational example of using the ARG instruction:

# ARG instruction Dockerfile for Docker Quick Start
FROM alpine
LABEL maintainer="Earl Waud <earlwaud@mycompany.com>"

ENV key1="ENV is stronger than an ARG"
RUN echo ${key1}
ARG key1="not going to matter"
RUN echo ${key1}

RUN echo ${key2}
ARG key2="defaultValue"
RUN echo ${key2}
ENV key2="ENV value takes over"
RUN echo ${key2}
CMD ["sh"]

Create a Dockerfile with the contents shown in the preceding code block and run the following build command to see how the scope of the ENV and ARG instructions play out:

# Build the image and look at the output from the echo commands
 docker image build --rm \
 --build-arg key1="buildTimeValue" \
 --build-arg key2="good till env instruction" \
 --tag arg-demo:2.0 .

You will see by the first echo ${key1} that even though there is a --build-arg parameter for key1, it will not be stored as key1 because there is an ENV instruction that has the same key name. This still holds true for the second echo ${key1}, which is after the ARG key1 instruction. The ENV variable values will always be the winner when there are both ARG and EVN instructions with the same key name.

Then, you will see that the first echo ${key2} is empty even though there is a --build-arg parameter for it. It is empty because we have not reached the ARG key2 instruction yet. The second echo ${key2} will contain the value from the corresponding --build-arg parameter even though there is a default value provided in the ARG key2 instruction. The final echo ${key2} will show the value provided in the ENV key2 instruction in spite of there being both a default value in the ARG and a value passed in via the --build-arg parameter. Again, this is because ENV always trumps ARG.

The difference between ENV and ARG

Again, here is a pair of instructions that have a similar functionality. They both can be used during the build of an image, setting parameters to be available to use within other Dockerfile instructions. The other Dockerfile instructions that can use these parameters are FROM, LABELCOPY, ADDENV, USER, WORKDIR, RUN, VOLUMEEXPOSE, STOPSIGNAL, and ONBUILD. Here is an example of using the ARG and ENV variables in other Docker commands:

# ENV vs ARG instruction Dockerfile for Docker Quick Start
FROM alpine
LABEL maintainer="Earl Waud <earlwaud@mycompany.com>"
ENV lifecycle="production"
RUN echo ${lifecycle}
ARG username="35"
RUN echo ${username}
ARG appdir
RUN echo ${appdir}
ADD hello /${appdir}/
RUN chown -R ${username}:${username} ${appdir}
WORKDIR ${appdir}
USER ${username}
CMD ["./hello"]

With this Dockerfile, you would want to provide --build-arg parameters for the appdir ARG instruction, and the username (if you want to override the default) to the build command. You could also provide an --env parameter at runtime to override the lifecycle variable. Here are possible build and run commands you could use:

# Build the arg3 demo image
docker image build --rm \
   --build-arg appdir="/opt/hello" \
   --tag arg-demo:3.0 .

# Run the arg3 demo container
docker container run --rm --env lifecycle="test" arg-demo:3.0

While the ENV and ARG instructions might seem similar, they are actually quite different. Here are the key differences to remember between the parameters created by the ENV and ARG instructions:

  • ENVs persist into running containers, ARGs do not.
  • ARGs use corresponding build parameters, ENVs do not.
  • ENV instructions must include both a key and a value, ARG instructions have a key but the (default) value is optional.
  • ENVs are more significant than ARGs.
You should never use either ENV or ARG instructions to provide secret data to the build command or resulting containers because the values are always visible in clear text to any user that runs the docker history command.

Comments are closed.

loading...