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.
.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.