DEV Community

Cover image for Docker ARG vs ENV: Understanding Build-time and Runtime Variables
Suleiman Dibirov
Suleiman Dibirov

Posted on

Docker ARG vs ENV: Understanding Build-time and Runtime Variables

Are you confused about when to use ARG versus ENV in your Dockerfiles? You're not alone! This comprehensive guide will help you understand the key differences, use cases, and best practices for both build arguments (ARG) and environment variables (ENV) in Docker.

Quick Reference

Feature ARG ENV
Available during build
Available in running container
Can be set in Dockerfile
Can be overridden at build time
Persists in final image
Can be used in FROM instruction

Key Differences

The fundamental difference between ARG and ENV lies in their scope and persistence:

  • ARG is only available during the build process
  • ENV sets environment variables that persist in the running container

Understanding ARG

Build arguments (ARG) are variables that you can pass to Docker during the image build process using the --build-arg flag.

Basic ARG Syntax

# Declare the argument
ARG VERSION=latest

# Use the argument
FROM ubuntu:${VERSION}
Enter fullscreen mode Exit fullscreen mode

Build command:

docker build --build-arg VERSION=20.04 -t my-ubuntu .
Enter fullscreen mode Exit fullscreen mode

ARG Scoping Rules

  1. ARGs declared before FROM are only available during FROM instruction
  2. To use ARG after FROM, you need to redeclare it
  3. Each FROM instruction clears all ARGs declared before it
# Global ARG
ARG BASE_IMAGE=ubuntu

# Available in FROM
FROM ${BASE_IMAGE}:latest

# Need to redeclare to use after FROM
ARG BASE_IMAGE
RUN echo "Building from ${BASE_IMAGE}"
Enter fullscreen mode Exit fullscreen mode

Understanding ENV

Environment variables (ENV) are set in your image and are available both during build and when the container runs.

Basic ENV Syntax

# Set a single environment variable
ENV APP_VERSION=1.0.0

# Set multiple environment variables
ENV NODE_ENV=production \
    PORT=3000 \
    APP_HOME=/app
Enter fullscreen mode Exit fullscreen mode

ENV Persistence

ENVs persist across build stages and in the final container:

# Stage 1: Build
FROM node:16 AS builder
ENV NODE_ENV=production
RUN echo "Building in ${NODE_ENV}"

# Stage 2: Runtime
FROM node:16-slim
# NODE_ENV needs to be redefined if needed in this stage
ENV NODE_ENV=production
Enter fullscreen mode Exit fullscreen mode

Real-World Examples

1. Building Different Versions of an Application

# Build argument for version control
ARG NODE_VERSION=16

# Base image with specified version
FROM node:${NODE_VERSION}

# Environment variable for runtime configuration
ENV NODE_ENV=production

# Redeclare ARG if needed after FROM
ARG NODE_VERSION
RUN echo "Node.js version: ${NODE_VERSION}"

# Application setup
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .

# Runtime configuration
ENV PORT=3000 \
    APP_NAME=my-awesome-app

CMD ["npm", "start"]
Enter fullscreen mode Exit fullscreen mode

2. Configurable Build Process

# Build-time configuration
ARG INSTALL_DEV_DEPS=false
ARG ENABLE_TESTING=false

FROM node:16

WORKDIR /app
COPY package*.json ./

# Redeclare ARGs after FROM
ARG INSTALL_DEV_DEPS
ARG ENABLE_TESTING

# Conditional installation of dependencies
RUN if [ "$INSTALL_DEV_DEPS" = "true" ]; then \
        npm install; \
    else \
        npm install --production; \
    fi

COPY . .

# Conditional testing
RUN if [ "$ENABLE_TESTING" = "true" ]; then \
        npm test; \
    fi

# Runtime configuration
ENV NODE_ENV=production \
    LOG_LEVEL=info

CMD ["npm", "start"]
Enter fullscreen mode Exit fullscreen mode

Best Practices

  1. Use ARG for Build Flexibility

    • Version numbers
    • Base image selection
    • Build-time configuration
  2. Use ENV for Runtime Configuration

    • Application settings
    • Service endpoints
    • Feature flags
  3. Default Values

   # Provide sensible defaults for ARGs
   ARG VERSION=latest
   ARG NODE_ENV=production

   # ENVs should also have defaults
   ENV PORT=3000 \
       LOG_LEVEL=info
Enter fullscreen mode Exit fullscreen mode
  1. Documentation
   # Document your build arguments
   # Required: VERSION - Specify the application version to build
   # Optional: NODE_ENV - Build environment (default: production)
   ARG VERSION
   ARG NODE_ENV=production
Enter fullscreen mode Exit fullscreen mode
  1. Security Considerations
    • Never use ARG or ENV for secrets
    • Use Docker secrets or environment files for sensitive data
    • Remember that ENVs are visible in the image history

Common Pitfalls

  1. ARG Scope Confusion
# Won't work as expected
ARG VERSION
FROM ubuntu:${VERSION}

# Need to redeclare
ARG VERSION
RUN echo ${VERSION}
Enter fullscreen mode Exit fullscreen mode
  1. Build-time vs Runtime Values
# Wrong: Using ARG for runtime configuration
ARG API_URL=http://api.example.com

# Correct: Use ENV for runtime configuration
ENV API_URL=http://api.example.com
Enter fullscreen mode Exit fullscreen mode
  1. Missing Defaults
# Risky: No default value
ARG VERSION

# Better: Include a default
ARG VERSION=latest
Enter fullscreen mode Exit fullscreen mode

Advanced Usage

Combining ARG and ENV

# Build argument with default
ARG NODE_ENV=production

# Set ENV based on ARG
ENV NODE_ENV=${NODE_ENV}

# Now NODE_ENV persists in the container
# but can be configured at build time
Enter fullscreen mode Exit fullscreen mode

Multiple Build Stages

# Build stage
FROM node:16 AS builder
ARG BUILD_MODE=production
ENV NODE_ENV=${BUILD_MODE}
RUN npm install && npm run build

# Production stage
FROM node:16-slim
ARG BUILD_MODE=production
ENV NODE_ENV=${BUILD_MODE}
COPY --from=builder /app/dist ./dist
Enter fullscreen mode Exit fullscreen mode

Using Docker Compose

services:
  app:
    build:
      context: .
      args:
        - NODE_VERSION=16
        - BUILD_MODE=development
    environment:
      - NODE_ENV=development
      - PORT=3000
Enter fullscreen mode Exit fullscreen mode

Conclusion

Understanding the difference between ARG and ENV is crucial for building flexible and maintainable Docker images. Use ARG for build-time configuration and ENV for runtime settings. Remember that ARGs are only available during build, while ENVs persist in the running container.

By following these guidelines and best practices, you can create more maintainable and configurable Docker images while avoiding common pitfalls.

Additional Resources

Top comments (0)