Docker Compose — Variable Substitution
Docker Compose supports shell-style variable substitution in compose.yml, powered by .env files or host environment variables.
Basic Substitution
services:
db:
image: postgres:${POSTGRES_TAG}
If POSTGRES_TAG=16 is set (in .env or shell), this resolves to postgres:16.
Default Values
services:
db:
image: postgres:${POSTGRES_TAG:-16} # Default: 16 if unset or empty
api:
image: myapi:${API_TAG-latest} # Default: latest if unset only
| Syntax | Meaning |
|---|---|
${VAR} |
Substitute value |
${VAR:-default} |
Default if unset or empty |
${VAR-default} |
Default if unset only |
Error on Missing
services:
db:
image: postgres:${POSTGRES_TAG:?Error: POSTGRES_TAG must be set}
If POSTGRES_TAG is unset or empty, Compose shows:
Error: POSTGRES_TAG must be set
| Syntax | Meaning |
|---|---|
${VAR:?error} |
Fail if unset or empty |
${VAR?error} |
Fail if unset only |
Replacement When Set
services:
api:
environment:
DEBUG: ${DEBUG:+enabled} # "enabled" if DEBUG is set and non-empty
| Syntax | Meaning |
|---|---|
${VAR:+replacement} |
Replacement if set and non-empty |
${VAR+replacement} |
Replacement if set (even if empty) |
Escaping Dollar Signs
Use $$ to output a literal $:
services:
api:
environment:
GREETING: "Price is $$5.00" # Resolves to: Price is $5.00
Priority of Variable Sources
| Priority | Source |
|---|---|
| 1 (highest) | Shell environment variable |
| 2 | .env file |
| 3 | Default in compose.yml (${VAR:-default}) |
Verify with docker compose config
Always verify substitution:
docker compose config
This outputs the fully resolved compose file.
Complete Example
.env:
PROJECT=myapp
DB_TAG=16
REDIS_TAG=7
API_PORT=3000
compose.yml:
services:
db:
image: postgres:${DB_TAG:-15}
container_name: ${PROJECT}-db
cache:
image: redis:${REDIS_TAG:?Redis tag required}
api:
image: ${PROJECT}-api:latest
ports:
- "${API_PORT:-8080}:3000"
Summary
| Pattern | Meaning | Example |
|---|---|---|
${VAR} |
Substitute | postgres:${TAG} |
${VAR:-default} |
Default if unset/empty | ${TAG:-16} |
${VAR:?error} |
Error if unset/empty | ${TAG:?required} |
${VAR:+alt} |
Alt if set | ${DEBUG:+enabled} |
$$ |
Literal $ | $$PATH |
Quick Reference
| Item | Detail |
|---|---|
| ${VAR} | Substitute variable value |
| ${VAR:-default} | Default if unset or empty |
| ${VAR:?error} | Fail with error if unset or empty |
| ${VAR:+replacement} | Replacement if set and non-empty |
| $$ | Literal dollar sign |
| docker compose config | Verify all substitutions |