Lesson 7 / 25

Interpolation and the .env File

${VAR:-default} at load time.

Values substituted before anything runs

Compose replaces ${VAR} in the file with values from your shell environment or from a .env file in the project directory, when it loads the file. ${VAR:-default} uses a default when the variable is unset or empty. Shell variables win over .env, which makes one-off overrides easy. Interpolation applies to the Compose file itself; it is different from environment, which sets variables inside containers. Commit a .env.example, not your real .env.

Configure per machine, validate before running

Variables fill in values at load time; config shows exactly what Compose will do.

Four ideas: .env interpolation, required variables, precedence, validation.
Figure 3.1 — Interpolation, required variables, precedence and validation.

.env values and a shell override, run

I ran this with Docker Compose v2.38.1 and jq in the demo "shop" project. docker compose config parses, interpolates, merges and validates the files without starting containers; the Docker daemon was not running, so nothing was started. With PG_VERSION=16 in .env, the db image resolves to postgres:16; setting PG_VERSION=17 in the shell for one command wins over .env and resolves to postgres:17.

cat .env
docker compose config --format json | jq -r ".services.db.image"
PG_VERSION=17 docker compose config --format json | jq -r ".services.db.image"

Output:

DB_PASSWORD=change-me-locally
PG_VERSION=16
postgres:16
postgres:17

Commit .env.example

List every variable with safe example values in .env.example and keep the real .env out of git.

Quick check: Which wins when a variable is set both in the shell and in .env?

  • The shell environment
  • .env
  • Whichever is longer
  • Neither; Compose errors
Answer

The shell environment — Shell values override .env.