ARG Instruction Reference

Last reviewed on 2026-05-02

Define build-time variables that users can pass at build-time

Syntax

ARG <name>[=<default value>]

The ARG instruction defines a variable that users can pass at build-time to the builder with the docker build command using the --build-arg <varname>=<value> flag.

The ARG instruction allows you to define variables that can be passed at build-time to customize your builds. Unlike ENV instructions, ARG values are not available to containers running from the final image.

ARG instructions are particularly useful for creating flexible Dockerfiles that can be customized without modification. They allow users to specify values like version numbers, repository URLs, or other build-specific configurations when they run docker build.

Description

The ARG instruction defines a variable that users can pass at build-time to the builder. This allows for dynamic configuration of the build process without changing the Dockerfile.

An ARG instruction can include a default value that will be used if no value is passed at build-time. For example:

ARG VERSION=latest

In this case, VERSION will default to "latest" if not specified by the user.

To pass a value at build-time, you would use the --build-arg flag:

docker build --build-arg VERSION=1.0 -t myimage .

ARG values can be referenced in subsequent Dockerfile instructions using the familiar shell syntax:

ARG VERSION=latest
FROM ubuntu:${VERSION}

Unlike ENV variables, ARG values do not persist in the built image. They are only available during the build process and not to containers created from the image. If you need a value to be available at runtime, you should use ENV instead, or combine ARG and ENV:

ARG VERSION=latest
ENV VERSION=${VERSION}

Scope and Precedence

ARG instructions have specific scoping rules in Dockerfiles:

Default Scope

An ARG instruction goes into effect from the line it is defined and lasts until the end of the build stage.

FROM ubuntu:20.04
# ARG VERSION is not available here
ARG VERSION=1.0
# ARG VERSION is available here and below
Pre-FROM ARG

ARG instructions defined before the first FROM are called "global" and can be used in any FROM instruction.

ARG BASE_IMAGE=ubuntu:20.04
FROM ${BASE_IMAGE}
# ARG BASE_IMAGE is still available here, but only for reference

These pre-FROM ARG values are not available for use inside instructions after the FROM line unless they are redefined with a new ARG instruction in that build stage.

Multi-stage ARG

In multi-stage builds, each FROM instruction starts a new build stage with its own scope.

ARG VERSION=1.0  # Global
FROM ubuntu:20.04 AS builder
ARG VERSION        # Redeclared in this stage
RUN echo ${VERSION}

FROM alpine:3.14 AS runner
ARG VERSION        # Must be redeclared in this stage too
RUN echo ${VERSION}
Predefined ARGs

Docker has a set of predefined ARG variables that you can use without declaring them:

  • HTTP_PROXY, http_proxy
  • HTTPS_PROXY, https_proxy
  • FTP_PROXY, ftp_proxy
  • NO_PROXY, no_proxy
  • TARGETPLATFORM, TARGETOS, TARGETARCH

These can be used directly in your Dockerfile:

FROM ubuntu:20.04
RUN echo "Building for architecture: ${TARGETARCH}"

Examples

Basic Usage

Defining a simple build argument with a default value:

FROM ubuntu:20.04
ARG VERSION=1.0
RUN echo "Building version: ${VERSION}"

The VERSION argument defaults to 1.0 but can be overridden at build time.

Dynamic Base Image

Using ARG to determine the base image:

ARG BASE_IMAGE=ubuntu:20.04
FROM ${BASE_IMAGE}
RUN echo "Using base image: ${BASE_IMAGE}"

This allows building from different base images without modifying the Dockerfile.

Package Installation

Using ARG to control which packages to install:

FROM ubuntu:20.04
ARG PACKAGES="vim curl git"
RUN apt-get update && apt-get install -y ${PACKAGES}

This makes it easy to customize which packages are installed during the build.

Setting Environment Variables

Combining ARG and ENV to set runtime configuration:

FROM node:18-alpine
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
RUN echo "Building with NODE_ENV=${NODE_ENV}"

This allows customizing the NODE_ENV value at build time, and persisting it for runtime.

Conditional Logic

Using ARG for conditional build steps:

FROM ubuntu:20.04
ARG ENVIRONMENT=production

RUN if [ "$ENVIRONMENT" = "development" ]; then \
      apt-get update && apt-get install -y vim git curl; \
    else \
      apt-get update && apt-get install -y curl; \
    fi

This example installs different packages based on the build environment.

Multi-stage Build with ARG

Using ARG in a multi-stage build:

ARG VERSION=latest

FROM node:18 AS builder
ARG VERSION
RUN echo "Building version: ${VERSION}"
# Build commands here...

FROM nginx:alpine AS runtime
ARG VERSION
LABEL version="${VERSION}"
# Copy from builder stage
COPY --from=builder /app/dist /usr/share/nginx/html

Note how the ARG needs to be redeclared in each stage to be available.

Best Practices

  • Provide default values: Always include sensible default values for ARG instructions to ensure the Dockerfile works without requiring build arguments.
  • Document ARG instructions: Add comments explaining what each ARG is for and what values are acceptable.
  • Use for build-time customization: Use ARG for values that should be customizable at build-time but don't need to be available at runtime.
  • Combine with ENV for runtime variables: If a value is needed at both build-time and runtime, define it with ARG and then set it as an ENV variable.
  • Be careful with secrets: ARG values are visible in the image history. Don't use ARG for sensitive information like passwords or API keys.
  • Group related ARG instructions: Place related ARG instructions together to make the Dockerfile more readable.
  • Consider multi-platform builds: Use ARG and BuildKit's predefined ARGs like TARGETARCH for multi-platform images.
  • Redeclare in each stage: Remember to redeclare ARG instructions in each build stage where they are needed.

ARG and the build cache

An ARG affects the layer cache only from the point at which its value is actually referenced. Declaring one costs nothing; using one invalidates every instruction below the reference whenever the value changes. That makes placement, not declaration, the thing to get right.

The common mistake is threading a per-build value — a commit SHA, a build timestamp — through the top of the Dockerfile:

# Slow: every commit changes GIT_SHA, so npm ci re-runs on every build
FROM node:20-alpine
ARG GIT_SHA
ENV GIT_SHA=${GIT_SHA}
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
# Fast: the dependency layer never sees GIT_SHA
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
ARG GIT_SHA
ENV GIT_SHA=${GIT_SHA}

The same property is occasionally useful in reverse. Because a changed ARG value busts everything below it, a deliberately-varied argument makes a reliable cache-buster for a step that must re-run:

docker build --build-arg CACHEBUST=$(date +%s) -t myapp .

Passing secrets: use a secret mount, not ARG

An ARG value is recorded in the image metadata and is visible to anyone who can pull the image:

docker build --build-arg NPM_TOKEN=npm_abc123 -t myapp .
docker history --no-trunc myapp    # the token is right there
docker image inspect myapp | grep -A5 Args

Squashing layers does not remove it, and neither does unsetting the variable in a later instruction. The supported answer is BuildKit's secret mount, which exposes the value as a file inside a single RUN and never writes it to a layer:

# syntax=docker/dockerfile:1.7
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc \
    npm ci --omit=dev
docker build --secret id=npmrc,src=$HOME/.npmrc -t myapp .

# Or straight from an environment variable
docker build --secret id=npmrc,env=NPM_CONFIG_USERCONFIG -t myapp .

For Git access over SSH, the equivalent is --mount=type=ssh with docker build --ssh default. Both are covered in the securing Docker builds tutorial. Reserve ARG for values you would happily print in a log: versions, feature flags, target architectures, repository URLs.

ARG vs ENV

It's important to understand the difference between ARG and ENV instructions:

ARG ENV
Only available at build time Available at both build time and runtime
Does not persist in the final image Persists in the final image
Can be set at build time with --build-arg Can be overridden at container runtime with -e
Used for build-time customization Used for runtime configuration

If you need a value only during the build process, use ARG. If you need a value to be available to the running container, use ENV.

You can combine ARG and ENV to create build-time configurable runtime environments:

ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}

This allows you to set NODE_ENV at build time with --build-arg, while still making it available at runtime as an environment variable.

Notes and Limitations

  • ARG values are not persisted in the final image, unlike ENV values.
  • ARG values are visible in the image history, so don't use them for secrets.
  • ARG instructions defined before a FROM are only available for use within FROM lines unless they are redeclared after the FROM.
  • Each build stage in a multi-stage build has its own scope for ARG values. You need to redeclare ARG in each stage where you want to use it.
  • ARG values can be overridden by environment variables with the same name when using docker build, but only if the ARG is defined in the Dockerfile.
  • Docker has a set of predefined ARG variables (like HTTP_PROXY, TARGETARCH) that you can use without declaring them.
  • ARG values can be referenced in almost all Dockerfile instructions, but there are some limitations with ONBUILD instructions.
  • The ARG instruction does not create a layer in the image like ENV does.