Docker build arguments let you set build-time variables that you can reference in your Dockerfile instructions. They make the Docker image build process configurable at build time.
In this article, we’ll explore how build args work and discuss the ways in which you can use them. Let’s begin!
Docker build args (build arguments) are variables that you can use in your Dockerfile. They don’t affect the image’s content on their own, but they allow you to template your Dockerfile so you can change how each build is performed.
Docker build arguments are defined in the Dockerfile and can be set or overridden during the build process using the --build-arg
flag.
Build args are essentially environment variables that exist only during the image-building phase. They’re not saved in the Docker image and can’t be accessed by running containers. To pass values into containers, environment variables must be used instead.
Build args are defined by the Dockerfile ARG
instruction. Once a variable has been defined, later Dockerfile instructions can reference its value:
ARG IMAGE_VERSION=3
FROM alpine:${IMAGE_VERSION}
Build argument values are populated at build-time via the docker build
command --build-arg
flag:
$ docker build --build-arg IMAGE_VERSION=latest -t example:latest .
This example causes the image to be built from the alpine:latest
base image, instead of the default value of alpine:3
.
The --build-arg
flag can only set build args that are actually defined in your Dockerfile. Specifying build args with no matching ARG
instruction won’t affect your build.
Using multiple build args
You can define multiple build args by repeating the ARG
instruction in your Dockerfile:
ARG foo
ARG bar
Each ARG allows you to pass different variables during the build process.
The --build-arg
build flag must then be repeated for each argument you want to set:
$ docker build --build-arg foo=example --build-arg bar=demo -t example:latest .
Populating build args from shell environment variables
You can use the --build-arg
flag without specifying a value for the arg. This will automatically look for a shell environment variable with the same name as the build arg and propagate the environment value into your build.
$ export MY_VAR=demo
# $MY_VAR is "demo" inside the build
$ docker build --build-arg MY_VAR -t example:latest .
This is a useful way to avoid hardcoding build arg values in scripts that call docker build
.
Making build args required
Docker always treats build args as optional. No error is thrown if you run docker build
command without a --build-arg
flag for one of your ARG
instructions. The following table summarizes the behavior:
ARG instruction |
--build-arg value |
Final value |
ARG foo |
Not Set | Empty |
ARG foo |
--build-arg foo=bar |
bar |
ARG foo=bar |
Not Set | bar |
ARG foo=bar |
--build-arg foo=demo |
demo |
If you’d like a build arg to require input, you can run the shell test
command during the build. Docker will interpolate the arg’s value into the command; test
then checks the input and exits with an error code if it’s empty. This will cause the build to fail.
ARG DEMO_VARIABLE
# build fails if there’s no --build-arg DEMO_VARIABLE flag
RUN test -n "${DEMO_VARIABLE}"
Using built-in build args
Docker includes a small set of predefined build args you can use without adding an ARG
instruction to your Dockerfile. These are currently:
HTTP_PROXY
HTTPS_PROXY
FTP_PROXY
NO_PROXY
ALL_PROXY
- Lowercase variants of all of the above.
You can always set values for these build args using --build-arg
.
The BuildKit build engine provides some additional predefined build args, which let you customize how BuildKit runs the build.
BuildKit also exposes access to certain build environment details via the following pre-populated build args:
BUILDPLATFORM
BUILDOS
BUILDARCH
BUILDVARIANT
TARGETPLATFORM
TARGETOS
TARGETARCH
TARGETVARIANT
You can access these build args by simply naming them in an ARG
instruction. There’s no need to set the --build-arg
flag:
ARG TARGETARCH
RUN curl https://example.com/my-binary-v1-${TARGETARCH}.tar
Build args eliminate hardcoding of Dockerfile values that users might have to change before a build. They also let you build many image variations from a single Dockerfile. This makes it easier to maintain your build configurations.
Common build arg use cases include:
- Setting version numbers or labels
- Changing the base image tag that you build from allows you to build both
node:20-bookworm
(Debian) andnode:20-alpine
(Alpine) flavors of your image. - Customizing which app features an image includes, such as by only
COPY
-ing a certain component into the image if a specific build arg is set. - Setting default container environment variables — for example, you could use build args to populate
BUILD_SHA
andBUILD_TIME
environment variables that your app can display.
Build args shouldn’t be used with secret values such as API tokens and credentials. Although build args aren’t visible inside containers, they’re part of the image’s metadata and can be retrieved with the docker history command. Use Docker’s build secrets mechanism to protect sensitive values and prevent them from being exposed to image users.
In Docker build, both build arguments (build args) and environment variables serve to configure the behavior of images and containers. Build args are for configuring what happens during docker build
, whereas environment variables (env variables) are values set inside running containers.
- Use a build arg if the value will be used by your Dockerfile instructions and doesn’t need to be saved in the image.
- Use an environment variable to set container values that can be read by your app.
It’s possible to use build args and environment variables together. This pattern allows build authors to set default values for environment variables:
FROM alpine:3
ARG NEW_FEATURE_ENABLED=0
ENV NEW_FEATURE_ENABLED=${NEW_FEATURE_ENABLED}
This Dockerfile defines a build arg called NEW_FEATURE_ENABLED
and then assigns its value to an environment variable with the same name. The value of NEW_FEATURE_ENABLED
inside the container will now match the value passed as --build-arg NEW_FEATURE_ENABLED
during the image build:
$ docker build --build-arg NEW_FEATURE_ENABLED=1 -t example:latest .
# prints "1"
$ docker run --rm example:latest sh -c 'echo $NEW_FEATURE_ENABLED'
If the ENV
instruction was removed from the Dockerfile the variable wouldn’t be set inside the container.
Container creators can still change the container variable’s value via the docker run command’s -e
/--env
flag:
# prints "0"
$ docker run --rm --env NEW_FEATURE_ENABLED=0 example:latest sh -c 'echo $NEW_FEATURE_ENABLED'
Build args have a few limitations to bear in mind. The first is simple: build args can only be used by the Dockerfile instructions that follow their definition. If you try to access a build arg before it’s defined, an empty string will always be returned:
# prints nothing
RUN echo ${foo}
ARG foo=bar
# prints bar
RUN echo ${foo}
Build args are also discarded at the end of each build stage. When you’re writing a multi-stage Dockerfile, you must include the ARG
instruction in every stage that needs a particular build arg.
FROM node:latest AS node
RUN npm install
ARG BUILD_VERSION
RUN echo $BUILD_VERSION > version.txt
FROM httpd:alpine AS httpd
ARG BUILD_VERSION
RUN echo $BUILD_VERSION > version.txt
If the second ARG
instruction was removed from this Dockerfile, the final RUN
statement wouldn’t have the expected result. The first ARG
instruction only applies to the stage that it’s defined in. This differs from the behavior of ENV
instructions.
Additionally, build args can only be referenced by Dockerfile instructions that support variable interpolation. These are:
ADD
COPY
ENV
EXPOSE
FROM
LABEL
STOPSIGGNAL
USER
VOLUME
WORKDIR
ONBUILD
Build arg references won’t be expanded when used in any other instruction.
We’ve explored Docker build arguments, a powerful mechanism for making your Docker image builds more customizable. Now you can easily create configurable builds that let you produce different image variants from a single Dockerfile.
Combine build args and environment variables to inject default container values at build-time. Just remember that build args won’t be automatically persisted in your image, until they’re manually assigned to an environment variable by an ENV instruction.
Ready to learn more techniques for improving your Docker image builds? Find more best practices in our guide to writing a Dockerfile.
We also encourage you to explore the ways Spacelift offers full flexibility when it comes to customizing your workflow. You can bring your own Docker image and use it as a runner to speed up deployments that leverage third-party tools. Spacelift’s official runner image can be found here.
If you want to learn more about what you can do with Spacelift, check out this article, create a free account today, or book a demo with one of our engineers.
Solve your infrastructure challenges
Spacelift is a flexible orchestration solution for IaC development. It delivers enhanced collaboration, automation, and controls to simplify and accelerate the provisioning of cloud-based infrastructures.