Environment Variables and Configuration
Configure containers without rebuilding them using -e and --env-file, understand ENV and ARG in a Dockerfile, and keep passwords out of your images.
On this page 10 sections
Introduction
The same image should run on your laptop, in testing and in production — only the configuration changes: database addresses, feature flags, API keys. The standard way to pass that configuration to a container is environment variables.
- How to set environment variables with -e and --env-file.
- The difference between ENV and ARG in a Dockerfile.
- How images such as PostgreSQL use required variables.
- Why secrets must never be written into a Dockerfile.
Setting Variables with -e
Priya’s Quotes API reads its greeting from the GREETING variable, with a default (look at os.environ.get in app.py from lesson 5). Without the variable, the API answers “Hello from Docker!”. With -e, the same image says something else — no rebuild needed:
docker run -d --name api -p 5000:5000 -e GREETING="Hello from Priya's laptop" quotes-apicurl http://localhost:5000/The JSON response now contains the new message. Repeat -e for each variable: -e APP_ENV=production -e LOG_LEVEL=debug. Writing -e GREETING without a value copies the variable from your own shell.
Env Files: --env-file
With many variables, put them in a file — one NAME=value per line, no quotes needed:
GREETING=Hello from the env file!APP_ENV=productiondocker run --rm --env-file .env quotes-api envenv (replacing CMD) prints every variable in the container, including GREETING and APP_ENV from the file, and others such as PATH and PYTHON_VERSION that come from the python base image. Keep env files with real secrets out of Git (.gitignore) and out of images (.dockerignore).
ENV and ARG in a Dockerfile
| ENV | ARG | |
|---|---|---|
| Available during build | Yes | Yes |
| Available in running containers | Yes | No |
| Set or overridden with | docker run -e | docker build --build-arg |
| Typical use | Defaults for the app (PYTHONUNBUFFERED=1, PORT=5000) | Build options (versions, build flags) |
They are often combined to bake a build-time value into the image:
FROM alpineARG APP_VERSION=1.0.0ENV APP_VERSION=$APP_VERSIONCMD ["sh", "-c", "echo Running version $APP_VERSION"]docker build -t versioned .docker run --rm versioned # Running version 1.0.0docker build --build-arg APP_VERSION=2.1.0 -t versioned:2.1.0 .docker run --rm versioned:2.1.0 # Running version 2.1.0Required Variables
Many official images are configured entirely through variables. PostgreSQL refuses to start without a password:
docker run --rm postgres:18-alpineIt exits with an error explaining that the database is uninitialised and you must specify POSTGRES_PASSWORD. The image documentation on Docker Hub lists every supported variable — for PostgreSQL also POSTGRES_USER and POSTGRES_DB:
docker run -d --name db -e POSTGRES_USER=app -e POSTGRES_PASSWORD=change-me -e POSTGRES_DB=shop postgres:18-alpineKeeping Secrets Safe
Environment variables are not hidden. Anyone who can run docker commands on the machine can read them:
docker inspect api --format "{{range .Config.Env}}{{println .}}{{end}}"Worse is a secret written into a Dockerfile with ENV. It becomes part of the image, and anyone who pulls the image can read it — even if a later step tries to remove it:
FROM alpineENV API_KEY=sk-live-1234567890docker history leaky # the API_KEY value is listed in plain text- Never put passwords, tokens or keys in a Dockerfile or copy .env files into an image.
- Pass secrets at run time with -e or --env-file, from a file that is not committed to Git.
- In production, prefer a secrets manager or Docker/Compose secrets, which mount secrets as files instead of variables.
- For secrets needed only during the build (such as a private package token), use BuildKit build secrets: RUN --mount=type=secret.
Which way of giving a container a database password is unsafe?
Common Mistakes
- Baking secrets into images with ENV, or copying .env files in with COPY . .
- Rebuilding an image just to change configuration — use variables instead.
- Putting quotes in env files expecting them to be removed; with --env-file they become part of the value.
- Expecting ARG values to exist in the running container — only ENV does.
Frequently Asked Questions
You need to recreate it: remove the container and run it again with the new value. Variables are fixed when a container is created.
A widely used set of guidelines for building cloud apps. One rule is to store configuration in the environment, which is exactly what this lesson does.
Yes — Compose automatically reads a .env file in the project folder and can use its values in compose.yaml. You will see this in the projects.
Key Takeaways
- Configure containers with -e NAME=value or --env-file file, without rebuilding.
- ENV sets variables in the image and containers; ARG only exists during the build.
- Official images such as PostgreSQL are configured through documented variables.
- Environment variables are visible with docker inspect; ENV values are visible in docker history.
- Never put secrets in a Dockerfile — supply them at run time or use a secrets mechanism.
Summary
You can now configure containers safely. Next you will stop typing long docker run commands altogether: Docker Compose describes a whole multi-container app in one file.