Environment variables
Configure a container at run time.
In plain terms
Environment variables are like setting the thermostat and preferences before someone moves into an apartment — same apartment, different settings each time. The image ships with sensible defaults; you dial in the specifics when you start it.
The clean way to configure a container is through environment variables, not by baking settings into the image. The same image can then run as dev, staging, or prod purely by changing its environment — the twelve-factor idea. You pass variables at run time with -e for one-offs, or --env-file to load a whole file of them.
terminal
$ docker run -d --name db \-e POSTGRES_PASSWORD=devsecret \-e POSTGRES_DB=payments \postgres:16$ docker run --env-file ./app.env myapp:1.0 # load many at once
Defaults live in the image
An image can declare default values with the ENV instruction in its Dockerfile, so the container works out of the box; anything you pass with -e at run time overrides those defaults. That layering — sensible defaults in the image, overrides at run time — is how a single image adapts to many environments without rebuilding.
Dockerfile
FROM node:22-alpineENV NODE_ENV=production \PORT=3000 # defaults; docker run -e PORT=8080 overrides themCOPY . /appWORKDIR /appCMD ["node", "server.js"]
Environment variables are not secret
A password passed with -e is visible in docker inspect, in the process environment, and often in logs and crash dumps — anyone who can inspect the container can read it. Env vars are fine for non-sensitive config; for real secrets, prefer mounted files or a secrets manager, a distinction the security courses treat in depth.