Environment Variables in Compose
Configure services with environment variables for flexible deployments.
Defining Variables
Inline Definition
services:
api:
environment:
- NODE_ENV=production
- PORT=3000
- DEBUG=false
# Or map syntax
environment:
NODE_ENV: production
PORT: 3000
DEBUG: "false"From .env File
services:
api:
env_file:
- .env
- .env.local # Overrides .env# .env
DATABASE_URL=postgres://user:pass@db:5432/app
REDIS_URL=redis://redis:6379
API_KEY=secret123Variable Substitution
services:
api:
image: myapp:${APP_VERSION:-latest}
environment:
- DATABASE_URL=${DATABASE_URL}
- API_KEY=${API_KEY}Variable Syntax
# Required variable (error if missing)
${VARIABLE}
# Default value if unset
${VARIABLE:-default}
# Default value if unset or empty
${VARIABLE-default}
# Error with message if unset
${VARIABLE:?error message}Environment File Priority
- Shell environment variables
.envfile in project directoryenv_filedirective in compose- Default values in compose file
Multiple Environment Files
services:
api:
env_file:
- .env # Base config
- .env.production # Production overrides# .env
DATABASE_HOST=localhost
DEBUG=true
# .env.production
DATABASE_HOST=prod-db.example.com
DEBUG=falsePer-Environment Compose Files
# docker-compose.yml (base)
services:
api:
build: .
environment:
- NODE_ENV=${NODE_ENV:-development}# docker-compose.prod.yml (override)
services:
api:
environment:
- NODE_ENV=production
- LOG_LEVEL=warn# Development
docker compose up
# Production
docker compose -f docker-compose.yml -f docker-compose.prod.yml upSecrets (Not Environment Variables)
services:
api:
secrets:
- db_password
- api_key
environment:
- DB_PASSWORD_FILE=/run/secrets/db_password
secrets:
db_password:
file: ./secrets/db_password.txt
api_key:
file: ./secrets/api_key.txtInterpolation in Compose
services:
api:
image: ${REGISTRY:-docker.io}/myapp:${VERSION:-latest}
ports:
- "${API_PORT:-3000}:3000"
deploy:
replicas: ${REPLICAS:-1}Complete Example
# docker-compose.yml
services:
api:
build: .
ports:
- "${API_PORT:-3000}:3000"
env_file:
- .env
environment:
- NODE_ENV=${NODE_ENV:-development}
- DATABASE_URL=postgres://${DB_USER}:${DB_PASS}@db:5432/${DB_NAME}
secrets:
- api_secret
db:
image: postgres:${POSTGRES_VERSION:-16}-alpine
environment:
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
POSTGRES_DB: ${DB_NAME}
secrets:
- db_password
secrets:
api_secret:
file: ./secrets/api.txt
db_password:
file: ./secrets/db.txt# .env
NODE_ENV=production
DB_USER=appuser
DB_NAME=myapp
API_PORT=8080
POSTGRES_VERSION=16Best Practices
- Never commit secrets - Add
.envto.gitignore - Use defaults - Provide sensible defaults with
:- - Validate required vars - Use
:?for critical config - Separate secrets - Use Docker secrets for sensitive data
- Document variables - Create
.env.exampletemplate
- docker compose
- environment
- env
- configuration
- secrets