Darragh ORiordan

  • About
  • Articles
  • Projects
  • Hire

Socials & Contact

  • Follow on Twitter
  • Follow on GitHub
  • Follow on LinkedIn
  • mailto:disco@darraghoriordan.com

Explore

  • About
  • Articles
  • Projects
  • Hire
  • Privacy Policy

© 2026 Darragh ORiordan. All rights reserved.

Docker Compose environment variables: precedence guide

  • #engineering
  • #cheatsheet
Photo by Adi Goldstein on Unsplash
Published April 23, 2023 · Updated September 3, 2026

Docker Compose has two related but different decisions to make: which values it uses while interpolating compose.yaml, and which environment variables finally reach a container. Keeping those stages separate makes the precedence rules much easier to reason about.

The quickest way to debug interpolation is docker compose config --environment. To inspect the fully resolved Compose model, run docker compose config.

Docker Compose interpolation syntax

Compose supports the following shell-style expressions inside compose.yaml:

ExpressionResult
${VARIABLE}Use the value, or an empty string if it is unset.
${VARIABLE:-default}Use default when the variable is unset or empty.
${VARIABLE-default}Use default only when the variable is unset.
${VARIABLE:?error}Exit with error when the variable is unset or empty.
${VARIABLE?error}Exit with error only when the variable is unset.
${VARIABLE:+replacement}Use replacement when the variable is set and non-empty.
${VARIABLE+replacement}Use replacement when the variable is set.

Interpolation source precedence

When Compose substitutes ${VARIABLE} in the model, the sources are evaluated from highest to lowest priority:

  1. The shell environment where you run docker compose.
  2. Files passed with --env-file, with later files overriding earlier ones.
  3. The project .env file when --env-file is not supplied.

An .env file supplies values for interpolation; it does not automatically put every value into the container. Reference a value under environment, or use a service-level env_file, when the container needs it.

services:
  api:
    image: example/api:${IMAGE_TAG:-latest}
    environment:
      NODE_ENV: ${NODE_ENV:-development}

Container environment variable precedence

For the final environment inside a container, the precedence is different. From highest to lowest:

  1. docker compose run -e VARIABLE=value
  2. An interpolated value in a service's environment or env_file attribute
  3. A literal value in the service's environment attribute
  4. A value in a service's env_file
  5. An ENV value baked into the image

The host shell and project .env file do not create container variables by themselves. They become container values only when the Compose model references them.

Debug the value Compose will use

# Show the inputs used for interpolation
docker compose config --environment

# Render the resolved Compose model
docker compose config

# Inspect a variable in a one-off container
docker compose run --rm api env | grep NODE_ENV

For the complete matrix and edge cases, use Docker's current guides to variable interpolation and container environment precedence.

Hey! Are you a developer?

🚀 Set Up Your Dev Environment in Minutes, Not Hours!

Tired of spending hours setting up a new development machine? I used to be, too—until I automated the entire process!

Now, I just run a single script, grab a coffee, and let my setup take care of itself.

Save 30+ hours configuring a new Mac or Windows (WSL) development environment.
Ensure consistency across all your machines.
Eliminate tedious setup and get coding faster!
Get Instant Access →