Docker ARG

Okay, here's a 20-post Twitter thread explaining the Docker ARG command.
Thread: Demystifying Docker's ARG Command 🐳⚙️ (1/20)
Ever needed to pass variables to your Docker build process without baking them permanently into the image? Meet the ARG instruction! Let's dive deep into how it works and when to use it. #Docker #DevOps #BuildKit
(2/20)
What is ARG?
The ARG instruction defines a variable that users can pass at build-time to the builder using the docker build command (--build-arg <varname>=<value>). Think of it as a parameter for your Dockerfile build process.
Example Dockerfile snippet:
ARG USER=guest
(3/20)
Declaring ARG:
You declare ARG in your Dockerfile before you use it. You can provide an optional default value.
Syntax:
ARG <name>
ARG <name>=<default_value>
If you don't provide a default and the user doesn't pass a value via --build-arg, the build might fail if the variable is used later.
(4/20)
Passing Values During Build:
Use the --build-arg flag with docker build. You can use it multiple times for multiple arguments.
Example:
docker build --build-arg USER=admin --build-arg VERSION=1.2.3 .
This would override the default guest value for USER in the Dockerfile from tweet 2.
(5/20)
Scope of ARG - Part 1:
An ARG declared before the first FROM statement is considered "outside" the build stages. It can be used to define the base image itself!
Example:
ARG BASE_IMAGE_TAG=latest
FROM ubuntu:${BASE_IMAGE_TAG}
docker build --build-arg BASE_IMAGE_TAG=22.04 .
(6/20)
Scope of ARG - Part 2:
An ARG declared inside a build stage (after a FROM) is only available within that specific stage. It goes out of scope when the stage ends or a new FROM starts.
ARG GLOBAL_ARG=hello
FROM ubuntu AS builder
ARG STAGE_ARG=world # Only available in 'builder' stage
RUN echo "${GLOBAL_ARG} ${STAGE_ARG}" # Prints "hello world"

FROM alpine
# STAGE_ARG is NOT available here
# GLOBAL_ARG is NOT available here unless redeclared

(7/20)
Scope of ARG - Part 3 (Redeclaration):
If you need an ARG declared before the first FROM to be available inside a stage, you MUST redeclare it (without the value) after the FROM.
ARG VERSION=latest
FROM ubuntu
ARG VERSION # Redeclares VERSION, inheriting the value passed via --build-arg or its default
RUN echo "Using version ${VERSION}"

(8/20)
ARG vs. ENV - The CRUCIAL Difference:
This trips people up!
* ARG: Build-time only. Values are NOT available in the container by default once it's running. They don't persist in the final image layers unless used to set an ENV.
* ENV: Runtime. Values ARE available to the container when it runs. They are baked into the image.
(9/20)
Why the ARG vs ENV difference matters:
Use ARG for things needed only during the build (e.g., specifying a package version, setting a user ID for RUN commands, conditional build logic). Use ENV for environment variables your application needs at runtime.
(10/20)
Using ARG to set ENV:
A common pattern is to use a build argument to set a runtime environment variable. The ARG value is used during the build, but the ENV value persists.
ARG APP_VERSION=1.0
ENV VERSION=${APP_VERSION} # ENV gets value from ARG at build time
# Now the container will have VERSION=1.0 (or whatever was passed) at runtime

(11/20)
Where can ARG be used?
ARG variables can be used in many subsequent instructions like RUN, COPY, ADD, USER, WORKDIR, ENV, EXPOSE, VOLUME, STOPSIGNAL, HEALTHCHECK, SHELL, and even in the FROM line (as seen earlier).
Example:
ARG USER=appuser
RUN adduser --disabled-password --gecos "" ${USER}
USER ${USER}
(12/20)
Use Case 1: Versioning:
Pass asset or application versions during build without hardcoding.
ARG ASSET_VERSION=v2
RUN wget "https://example.com/assets-${ASSET_VERSION}.zip"

Build with: docker build --build-arg ASSET_VERSION=v3 .
(13/20)
Use Case 2: User/Group IDs:
Match container UIDs/GIDs with host users, especially useful in development.
ARG USER_ID=1000
ARG GROUP_ID=1000
RUN groupadd -g ${GROUP_ID} mygroup && \
   useradd -u ${USER_ID} -g ${GROUP_ID} -ms /bin/bash myuser
USER myuser

Build with: docker build --build-arg USER_ID=$(id -u) --build-arg GROUP_ID=$(id -g) .
(14/20)
Use Case 3: Conditional Builds (Simplified):
While Dockerfiles lack complex logic, ARG can help select sources or configurations.
ARG SOURCE_REPO=mainline
COPY sources/${SOURCE_REPO}/config.conf /etc/app/config.conf

Build with: docker build --build-arg SOURCE_REPO=experimental .
(15/20)
Default Values Recap:
Defaults are handy! If --build-arg isn't provided, the default is used.
ARG GREETING="Hello"
RUN echo $GREETING
If built with no --build-arg GREETING=..., it echoes "Hello". If built with --build-arg GREETING=Hi, it echoes "Hi".
(16/20)
⚠️ Security Warning: DON'T use ARG for Secrets! ⚠️
Build arguments are not secure for secrets like passwords or API keys. They can be easily inspected using docker history.
Why? Because the value might be embedded in the command line of a RUN instruction, which is stored in the image layer history.
(17/20)
Secure Alternative for Secrets:
For passing secrets during build, use BuildKit's --secret mount feature. This mounts the secret securely during the build without baking it into the image history.
RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret
Build with: docker build --secret id=mysecret,src=mysecret.txt .
(18/20)
Predefined ARGs:
Docker defines some ARGs automatically if your build environment has corresponding env vars set (e.g., proxy settings):
HTTP_PROXY, HTTPS_PROXY, FTP_PROXY, NO_PROXY
These are automatically available to instructions like RUN apt-get update without explicit ARG declaration in the Dockerfile.
(19/20)
Best Practices:
* Use descriptive names for your ARGs.
* Provide sensible defaults where possible.
* Remember the scope rules (before/after FROM, redeclaration).
* Clearly distinguish between ARG (build-time) and ENV (runtime).
* NEVER use ARG for sensitive data. Use --secret.
(20/20)
In Summary:
ARG is a powerful tool for parameterizing your Docker builds, making them more flexible and reusable. Understand its scope, its difference from ENV, and its security implications to use it effectively!
Happy Dockering! 🐳✨ #DockerTips #Containers #CI #CD