Docker Environment Variables
Docker Environment Variables
Section titled “Docker Environment Variables”Configuration that varies between environments (dev, staging, prod) should be passed to containers via environment variables — not baked into the image.
Passing Environment Variables
Section titled “Passing Environment Variables”# Single variabledocker run -e NODE_ENV=production my-app
# Multiple variablesdocker run \ -e NODE_ENV=production \ -e PORT=3000 \ -e DATABASE_URL=postgresql://db:5432/prod \ my-app
# From a filedocker run --env-file .env my-app.env Files
Section titled “.env Files”NODE_ENV=productionPORT=3000DATABASE_URL=postgresql://db:5432/myappJWT_SECRET=super-secret-keydocker run --env-file .env my-appNever commit .env files with real secrets. Commit .env.example with placeholder values instead.
In Dockerfile
Section titled “In Dockerfile”# Set a default value (can be overridden at runtime)ENV NODE_ENV=productionENV PORT=3000
# Or on one lineENV NODE_ENV=production PORT=3000ARG vs ENV:
ARG— available only during build time (docker build --build-arg NAME=value)ENV— available at build time AND at runtime in the container
ARG APP_VERSION=1.0.0ENV APP_VERSION=${APP_VERSION} # promote ARG to ENV for runtime accessDocker Compose
Section titled “Docker Compose”services: api: image: my-app environment: NODE_ENV: production PORT: 3000 DATABASE_URL: postgresql://db:5432/myappOr reference host environment variables:
services: api: environment: - NODE_ENV # inherits from host shell - DATABASE_URL # inherits from host shell - JWT_SECRET=${MY_SECRET_VAR} # maps a differently-named host varUsing an env file in Compose:
services: api: env_file: - .env - .env.production # overrides .env for productionSecrets Management
Section titled “Secrets Management”For sensitive values in production, use dedicated secret management:
Docker Swarm Secrets:
echo "my-db-password" | docker secret create db-password -
docker service create \ --secret db-password \ my-appInside the container the secret is mounted at /run/secrets/db-password.
Kubernetes Secrets:
env: - name: DB_PASSWORD valueFrom: secretKeyRef: name: db-credentials key: passwordCloud Secret Managers:
- Azure Key Vault → inject via App Service config or Kubernetes CSI driver
- AWS Secrets Manager → IAM role + SDK or Kubernetes External Secrets
- GCP Secret Manager → Workload Identity +
--set-secretsin Cloud Run
Reading Variables in Node.js
Section titled “Reading Variables in Node.js”const port = parseInt(process.env.PORT ?? '3000', 10);const dbUrl = process.env.DATABASE_URL;if (!dbUrl) throw new Error('DATABASE_URL is required');Variable Precedence in Compose
Section titled “Variable Precedence in Compose”When a variable is defined in multiple places, Compose applies this priority (highest first):
- Values set with
docker compose run -e VAR=value - Shell environment variables
environment:indocker-compose.ymlenv_file:filesENVin the Dockerfile
Security Best Practices
Section titled “Security Best Practices”- Never hardcode secrets in Dockerfile or docker-compose.yml
- Never pass secrets as
ARG— they appear indocker history - Use
--env-filewith files outside source control for local dev - In CI/CD, inject secrets through the pipeline’s secret store (GitHub Actions Secrets, GitLab CI Variables)
- In production, use a dedicated secret manager rather than
.envfiles on servers - Scan images for secrets with tools like
trufflehogorgitleaks