Docker has revolutionized software development by simplifying how we package, distribute, and deploy applications. One of its most powerful features is the ability to customize the build process using Docker build arguments. These build-time variables provide flexibility and allow developers to tailor their images for specific use cases. In this article, we’ll explore the intricacies of Docker build arguments, their use cases, and best practices for integrating them effectively into your workflows.
Understanding Docker Build Arguments
Docker build arguments, or build args, are variables available only during the image build phase. Defined in a Dockerfile using the ARG
instruction, they enable developers to create configurable and reusable build scripts. These arguments are passed at build time via the --build-arg
flag in the docker build
command.
Unlike environment variables (ENV
), build args:
- Exist solely during the build process.
- Do not persist in the resulting image.
- Are not accessible within containers running from the image.
Here’s a simple example:
# Dockerfile
ARG IMAGE_VERSION=3
FROM alpine:${IMAGE_VERSION}
This example allows you to dynamically change the base image version during the build process:
docker build --build-arg IMAGE_VERSION=latest -t my-image:latest .
By passing IMAGE_VERSION=latest
, the image is built from alpine:latest
instead of the default alpine:3
.
Benefits of Using Docker Build Arguments
Build args provide several advantages that enhance Docker’s flexibility:
- Customizable Builds:
- Dynamically adjust configurations, such as selecting specific versions of a base image.
- Create multiple variations of the same image by tweaking build parameters.
- Improved Maintainability:
- Reduce redundancy by consolidating variations into a single Dockerfile.
- Enable dynamic features without modifying the Dockerfile itself.
- Scripting Convenience:
- Integrate with environment variables to avoid hardcoding values in scripts.
- Simplify CI/CD pipelines by passing build-specific variables.
Defining and Using Build Args in Dockerfiles
1. Declaring Build Args: To declare a build arg in a Dockerfile, use the ARG
instruction. Optionally, you can provide a default value:
ARG VAR_NAME=default_value
Multiple build args can be defined:
ARG FOO
ARG BAR=42
2. Referencing Build Args: Build args can be used in supported instructions like FROM
, RUN
, LABEL
, and ENV
:
ARG APP_VERSION
LABEL version=${APP_VERSION}
3. Passing Build Args: Pass values for build args using the --build-arg
flag:
docker build --build-arg FOO=example --build-arg BAR=100 -t my-image .
If a value isn’t specified, the default value from the Dockerfile is used.
Advanced Features and Best Practices
Using Build Args from Shell Variables
To streamline builds, you can pass shell environment variables directly as build args:
export APP_ENV=production
docker build --build-arg APP_ENV -t my-image .
This propagates the value of APP_ENV
from the shell to the build process.
Making Build Args Mandatory
By default, Docker treats build args as optional. However, you can enforce required input using shell validation within the Dockerfile:
ARG REQUIRED_ARG
RUN test -n "${REQUIRED_ARG}" || exit 1
If REQUIRED_ARG
is not provided, the build fails with an error.
Predefined Build Arguments
Docker provides several built-in build args that require no explicit ARG
declaration. These include:
- Proxy settings (
HTTP_PROXY
,HTTPS_PROXY
, etc.). - Build environment details:
BUILDPLATFORM
,BUILDOS
,BUILDARCH
, andBUILDVARIANT
for the current build context.TARGETPLATFORM
,TARGETOS
,TARGETARCH
, andTARGETVARIANT
for the target platform.
Example usage:
ARG TARGETARCH
RUN curl -O https://example.com/binary-${TARGETARCH}.tar.gz
Common Use Cases for Build Args
- Versioning and Tagging:
- Dynamically set base image tags.
- Define application versions or build metadata.
- Feature Toggles:
- Enable or disable optional components or features at build time.
- Use build args to populate container environment variables:
- Default Environment Variables:
- Default Environment Variables:
- Platform-Specific Builds:
- Use predefined build args like
TARGETARCH
to create architecture-specific images.
- Use predefined build args like
Limitations of Docker Build Arguments
While build args are a powerful tool, they have some limitations:
- Scope
Build args are available only after their declaration and are discarded at the end of each build stage. In multi-stage builds, you must redefine build args in every stage where they’re needed:
ARG BUILD_VERSION
FROM alpine AS base
RUN echo ${BUILD_VERSION}
FROM scratch
ARG BUILD_VERSION
RUN echo ${BUILD_VERSION}
2. Limited Instructions:
-
- Build args work only with instructions like
FROM
,RUN
, andLABEL
. Unsupported instructions will ignore them.
- Build args work only with instructions like
3. Not Suitable for Secrets:
-
-
- Build args are stored in image metadata and can be retrieved using
docker history
. For secrets, use Docker’s build secrets.
- Build args are stored in image metadata and can be retrieved using
-
Build Args vs. Environment Variables (ARG vs. ENV)
Build args and environment variables serve different purposes:
Aspect | Build Args | Environment Variables |
---|---|---|
Scope | Build phase only | Runtime inside containers |
Persistence | Not saved in the image | Saved in the image and accessible |
Usage | Configure build behavior | Configure container behavior |
To combine both, assign build arg values to environment variables:
ARG FEATURE_ENABLED=0
ENV FEATURE_ENABLED=${FEATURE_ENABLED}
Real-World Example: Multi-Stage Build with Build Args
Here’s a practical example of using build args in a multi-stage Dockerfile:
ARG NODE_VERSION=16
FROM node:${NODE_VERSION} AS builder
WORKDIR /app
COPY . .
RUN npm install && npm run build
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
In this setup:
- The
NODE_VERSION
build arg specifies the Node.js version. - The build stage compiles the app using the specified Node.js version.
- The production stage uses Nginx to serve the compiled files.
Conclusion
Docker build arguments are a powerful tool for creating customizable and reusable Dockerfiles. They simplify dynamic configurations, enable versioning, and improve maintainability. By combining build args with environment variables, developers can ensure flexible and robust builds tailored to diverse needs.
Want to master more Docker techniques? Follow CereBrix for expert insights and practical guides. Stay connected with us on social media at @cerebrixorg!