1.05 Docker Environment Variables
Overview
Environment variables allow you to pass runtime configuration into containers without modifying application code. They decouple config from code β a core principle of the 12-Factor App.
Abstract
Instead of hardcoding values like colors, ports, or database URLs inside your application, you inject them as environment variables at runtime. This makes the same Docker image reusable across dev, staging, and production by simply changing the environment β not the code.
Why It Matters in Production
Hardcoded config values force code changes for every environment. Environment variables let you:
- Run the same image across multiple environments with different settings
- Rotate secrets and config without rebuilding images
- Follow security best practices by keeping secrets out of source control
Key Concepts
| Concept | Description |
|---|---|
os.environ.get('VAR') |
Python method to read an env var at runtime |
-e flag |
docker run option to inject an env var into the container |
docker inspect |
Command to view all env vars set on a running container |
Config.Env |
Section in docker inspect output listing all container env vars |
Common Use Cases
- Setting a UI theme or color without redeploying code
- Passing database connection strings (host, port, credentials)
- Configuring feature flags per environment
- Setting log levels (DEBUG in dev, ERROR in prod)
- Injecting API keys or tokens at container startup
Example Configuration or Commands
Application Code β Reading an Env Var
import os
from flask import Flask
app = Flask(__name__)
color = os.environ.get('APP_COLOR')
@app.route("/")
def main():
print(color)
return render_template('hello.html', color=color)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080)
Setting an Env Var Before Running Locally
Passing Env Vars with docker run
# Single env var with -e flag
docker run -e APP_COLOR=blue simple-webapp-color
# Deploy the same image with a different color
docker run -e APP_COLOR=green simple-webapp-color
# Another instance with a different value
docker run -e APP_COLOR=pink simple-webapp-color
Inspecting Env Vars on a Running Container
The Config.Env section of the output will show all set variables:
"Config": {
"Env": [
"APP_COLOR=blue",
"LANG=C.UTF-8",
"GPG_KEY=0D96DF4D4110E5C43FBFB17F2D347EA6AA65421D",
"PYTHON_VERSION=3.6.6",
"PYTHON_PIP_VERSION=18.1"
]
}
Using --env-file for Multiple Variables
# Pass multiple env vars from a file (preferred for many vars)
docker run --env-file ./app.env simple-webapp-color
Best Practices
Best Practices
- Externalize all environment-specific config (ports, hostnames, feature flags, colors) as env vars β never hardcode them
- Use
--env-fileto manage multiple variables cleanly rather than chaining-eflags - Provide sensible defaults in application code with
os.environ.get('VAR', 'default')for non-sensitive values - Document all required env vars in your project's README or a
.env.examplefile - Use
docker inspect <container>to audit what variables are active in any running container
Security Best Practices
Security
- Never pass secrets (passwords, API keys, tokens) via
-eon the command line β they appear in shell history anddocker inspectoutput in plain text - Use Docker Secrets, Vault, AWS Secrets Manager, or Kubernetes Secrets for sensitive values in production
- Do not commit
.envfiles containing real credentials to source control β add them to.gitignore - Rotate credentials regularly; injecting them as env vars (rather than baking into images) makes rotation straightforward
- Prefer
--env-fileover inline-eflags in scripts β the file can have tighter filesystem permissions
Do and Don't
| β Do | β Don't |
|---|---|
Use -e APP_COLOR=blue to pass config at runtime |
Hardcode config values inside application source code |
Use --env-file for multiple env vars |
Chain many -e flags on a single long command |
| Store secrets in a secrets manager | Pass passwords via -e on the CLI |
Add .env to .gitignore |
Commit real credentials in .env files |
Use docker inspect to audit running container config |
Assume env vars are set without verifying |
| Provide defaults in code for optional vars | Let the app crash silently when an env var is missing |
Common Mistakes
Common Mistakes
- Forgetting to export the variable locally (
export APP_COLOR=blue) before running βAPP_COLOR=blue python app.pyonly sets it for that single command - Passing the
-eflag after the image name β flags must come before the image name indocker run - Expecting env vars set on the host to automatically propagate into the container β they don't unless explicitly passed with
-e VARor-e VAR=value - Storing sensitive env vars in a
DockerfileusingENVβ they get baked into image layers and are visible indocker history
Troubleshooting
Check which env vars are active inside a container
# Option 1: docker inspect (from the host)
docker inspect <container_name_or_id>
# Option 2: exec into the container and print env
docker exec -it <container_name> env
Confirm the app is reading the variable
# Exec into the container and check the specific variable
docker exec -it <container_name> printenv APP_COLOR
Variable is set but app ignores it
- Confirm the app reads it at startup, not at import time before the variable is injected
- Check for typos β env var names are case-sensitive (
APP_COLORβapp_color)
Quick Recap
- Environment variables decouple config from code β the same image runs anywhere with different settings
- Use
docker run -e KEY=VALUE imageto inject env vars at container startup - Deploy multiple containers from the same image with different env vars using separate
docker runcommands - Use
docker inspect <container>βConfig.Envto view all env vars on a running container - Never hardcode secrets in images; use a secrets manager or vault in production
Interview / Revision Notes
-
Q: How do you pass an environment variable to a Docker container? Use
docker run -e KEY=VALUE imageordocker run --env-file file.env image -
Q: How do you check which env vars are set on a running container?
docker inspect <container>β look underConfig.Env -
Q: Why should secrets not be passed via
-eon the CLI? They are stored in shell history and visible in plain text viadocker inspect -
Q: What is the advantage of using
--env-fileover multiple-eflags? Cleaner commands, easier management, and the file can have restricted permissions -
Q: Does setting an env var on the host automatically pass it into the container? No β it must be explicitly forwarded with
-e VARNAMEor-e VARNAME=value