docker-compose
environment-variables
docker
devops
containerization

How to pass environment variable to docker-compose up

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Docker Compose supports several ways to pass environment variables to containers. You can define them inline in docker-compose.yml with the environment key, load them from .env files, or pass them from the host shell. The .env file in the same directory as docker-compose.yml is automatically loaded for variable substitution in the Compose file itself, while env_file loads variables directly into the container.

Method 1: Inline in docker-compose.yml

Define variables directly under the environment key:

yaml
1services:
2  web:
3    image: node:20
4    environment:
5      - NODE_ENV=production
6      - DATABASE_URL=postgres://db:5432/app
7      - DEBUG=false
8    ports:
9      - "3000:3000"

Or use the mapping syntax:

yaml
1services:
2  web:
3    image: node:20
4    environment:
5      NODE_ENV: production
6      DATABASE_URL: postgres://db:5432/app
7      DEBUG: "false"

Method 2: .env File (Auto-loaded)

Docker Compose automatically reads a .env file in the project directory. Variables from this file are available for ${VAR} substitution in docker-compose.yml:

bash
1# .env
2APP_PORT=8080
3DB_PASSWORD=secret123
4NODE_ENV=production
yaml
1# docker-compose.yml
2services:
3  web:
4    image: node:20
5    ports:
6      - "${APP_PORT}:3000"
7    environment:
8      - NODE_ENV=${NODE_ENV}
9      - DB_PASSWORD=${DB_PASSWORD}
bash
docker-compose up
# APP_PORT, DB_PASSWORD, NODE_ENV are substituted from .env

Method 3: Shell Environment Variables

Variables set in the host shell override .env file values:

bash
1# Set in shell
2export NODE_ENV=development
3export DB_PASSWORD=devpass
4
5# These override .env values
6docker-compose up
yaml
1services:
2  web:
3    image: node:20
4    environment:
5      # Pass-through: uses value from host shell or .env
6      - NODE_ENV
7      # With default: uses host value, falls back to "production"
8      - NODE_ENV=${NODE_ENV:-production}

Method 4: Inline on Command Line

Pass variables for a single command:

bash
1# Single variable
2NODE_ENV=staging docker-compose up
3
4# Multiple variables
5NODE_ENV=staging DB_HOST=localhost docker-compose up -d
6
7# Or use export
8export NODE_ENV=staging
9docker-compose up

Method 5: env_file Directive

Load variables from a file directly into the container (different from .env substitution):

bash
1# config/app.env
2NODE_ENV=production
3API_KEY=abc123
4LOG_LEVEL=info
yaml
1services:
2  web:
3    image: node:20
4    env_file:
5      - ./config/app.env
6    # env_file loads vars INTO the container
7    # .env loads vars for docker-compose.yml substitution

You can use multiple env files:

yaml
1services:
2  web:
3    image: node:20
4    env_file:
5      - ./config/common.env
6      - ./config/app.env
7      - ./config/secrets.env
8    # Later files override earlier ones

Method 6: docker-compose --env-file

Override the default .env file location:

bash
# Use a different env file for substitution
docker-compose --env-file ./config/staging.env up

Variable Precedence

When the same variable is defined in multiple places, Docker Compose uses this priority order (highest to lowest):

  1. Shell environment variables
  2. .env file (for Compose file substitution)
  3. environment key in docker-compose.yml
  4. env_file directive
  5. Dockerfile ENV instructions
yaml
1services:
2  web:
3    image: node:20
4    env_file:
5      - ./defaults.env          # Lowest priority (among these)
6    environment:
7      - NODE_ENV=production     # Overrides env_file
8      # Shell export overrides this

Per-Environment Overrides

Use multiple Compose files for different environments:

bash
1# docker-compose.yml (base)
2# docker-compose.override.yml (dev — auto-loaded)
3# docker-compose.prod.yml (production)
4
5# Development (auto-loads override)
6docker-compose up
7
8# Production
9docker-compose -f docker-compose.yml -f docker-compose.prod.yml up
yaml
1# docker-compose.prod.yml
2services:
3  web:
4    environment:
5      - NODE_ENV=production
6      - LOG_LEVEL=warn

Verifying Variables

bash
1# See resolved config with all variables substituted
2docker-compose config
3
4# Check specific service environment
5docker-compose run --rm web env | sort
6
7# Inspect running container
8docker exec my-container env

Common Pitfalls

  • Confusing .env with env_file: The .env file provides variables for ${VAR} substitution in docker-compose.yml. The env_file directive loads variables into the container runtime. They serve different purposes.
  • Unquoted values with spaces: In .env and env_file files, values with spaces do not need quotes. MY_VAR=hello world sets the value to hello world. Adding quotes includes them literally: MY_VAR="hello" sets the value to "hello" (with quotes).
  • Committing secrets to .env: Add .env to .gitignore when it contains passwords, API keys, or other secrets. Use Docker secrets or a vault for production credentials.
  • Variable substitution not working in env_file: ${VAR} syntax only works in docker-compose.yml, not inside env_file referenced files. Variables in env_file are literal — no substitution is performed.
  • Missing variable warning: If ${VAR} is used in docker-compose.yml but not set anywhere, Docker Compose substitutes an empty string and prints a warning. Use ${VAR:-default} to provide a fallback value.

Summary

  • Use environment in docker-compose.yml for simple, non-sensitive variables
  • Use .env file for variable substitution in the Compose file (auto-loaded from project directory)
  • Use env_file to load variables directly into containers from external files
  • Shell environment variables have the highest priority and override all other sources
  • Use docker-compose config to verify resolved variable values before deploying

Course illustration
Course illustration

All Rights Reserved.