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)