HxHippy

Build Arguments & Variables

Dynamic builds with ARG, ENV, and build-time variables.

Last updated: 2025-01-15

Build-Time Variables

Control builds dynamically with ARG and ENV.

ARG - Build-Time Variables

# Define build argument
ARG NODE_VERSION=20
FROM node:${NODE_VERSION}-alpine

# Use with default
ARG APP_VERSION=1.0.0
LABEL version="${APP_VERSION}"

# Required argument (no default)
ARG API_URL
RUN echo "API: ${API_URL}"
# Override at build time
docker build --build-arg NODE_VERSION=18 -t myapp .
docker build --build-arg APP_VERSION=2.0.0 -t myapp .
docker build --build-arg API_URL=https://api.example.com -t myapp .

ENV - Runtime Variables

# Set environment variables
ENV NODE_ENV=production
ENV PORT=3000

# Multiple variables
ENV NODE_ENV=production \
    PORT=3000 \
    LOG_LEVEL=info

# Available at runtime
CMD echo "Running on port ${PORT}"

ARG vs ENV

Aspect ARG ENV
Available Build time only Build + Runtime
Override --build-arg -e or --env
Persists No (not in image) Yes (in image)
Use case Version, URLs Config, settings

Converting ARG to ENV

# ARG only available during build
ARG APP_VERSION=1.0.0

# Convert to ENV for runtime
ENV APP_VERSION=${APP_VERSION}

# Now available at runtime
CMD echo "Version: ${APP_VERSION}"

Predefined ARGs

# Docker provides these automatically
ARG TARGETPLATFORM
ARG TARGETOS
ARG TARGETARCH
ARG BUILDPLATFORM
ARG BUILDOS
ARG BUILDARCH

# Use for multi-platform builds
FROM --platform=${BUILDPLATFORM} golang:1.22 AS builder
RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -o app

Practical Examples

Version-Based Builds

ARG NODE_VERSION=20
ARG ALPINE_VERSION=3.19

FROM node:${NODE_VERSION}-alpine${ALPINE_VERSION}

ARG APP_VERSION=dev
ENV APP_VERSION=${APP_VERSION}

LABEL version="${APP_VERSION}"
# Build with specific versions
docker build \
  --build-arg NODE_VERSION=18 \
  --build-arg APP_VERSION=1.2.3 \
  -t myapp:1.2.3 .

Environment-Specific Builds

ARG ENVIRONMENT=production

FROM node:20-alpine

ARG ENVIRONMENT
ENV NODE_ENV=${ENVIRONMENT}

COPY package*.json ./
RUN if [ "${ENVIRONMENT}" = "development" ]; then \
      npm install; \
    else \
      npm ci --only=production; \
    fi

COPY . .
CMD ["node", "server.js"]

Private Registry Authentication

ARG REGISTRY_URL=docker.io
ARG BASE_IMAGE=node:20-alpine

FROM ${REGISTRY_URL}/${BASE_IMAGE}
# ...

Security Considerations

# Bad: Secrets visible in image history
ARG SECRET_KEY
RUN curl -H "Authorization: ${SECRET_KEY}" https://api.example.com

# Good: Use BuildKit secrets
RUN --mount=type=secret,id=api_key \
    curl -H "Authorization: $(cat /run/secrets/api_key)" https://api.example.com
# Pass secret at build time
docker build --secret id=api_key,src=./api_key.txt -t myapp .

Best Practices

  1. Use defaults - Always provide sensible defaults for ARG
  2. Document ARGs - Comment what each ARG is for
  3. Don't expose secrets - ARG values visible in docker history
  4. Convert to ENV - When runtime access is needed
  5. Use in FROM - ARG before FROM for base image selection
intermediate Dockerfile Updated 2025-01-15
  • dockerfile
  • arg
  • env
  • variables
  • build-time