Skip to content

🔐 Docker Environment Variables & Secrets

The Complete Guide for DevOps & Backend Engineers (With Hands-On Labs)

Docker makes packaging and running applications easy — but config & secrets management is where most beginners make mistakes.

This guide covers:

  • .env files

  • Environment variables

  • Passing configs securely

  • Docker Compose best practices

  • Docker Secrets (Swarm)

  • Avoiding accidental secret leaks

  • Hands-on labs

  • Interview questions

Let’s go deep.


1️⃣ Why Environment Variables Matter

Traditional apps load config from files.
Containers load config from environment variables, enabling:

✔ Immutable images
✔ Configurable deployments
✔ CI/CD-friendly pipelines
✔ Easy switching between environments
✔ Avoiding secrets inside images

A modern production workflow looks like:

Build → Push → Deploy ↘ configs/secrets applied at runtime


2️⃣ Passing Environment Variables to Containers

Method 1 — Using -e flag

docker run -e PORT=3000 -e NODE_ENV=production node-app

Method 2 — Using an env file

.env

PORT=3000 DB_USER=admin DB_PASS=strongpass

Run:

docker run --env-file .env node-app

This is better, cleaner, portable.

Method 3 — Docker Compose

app: image: node-app environment: - PORT=3000 - DB_USER=admin

or load .env automatically (Compose does this by default).


3️⃣ How .env Files Work (Most Misunderstood Topic)

docker-compose automatically loads .env from the directory where docker-compose.yml exists.

Example:

.env docker-compose.yml

Variables inside:

APP_NAME=myapp PORT=8000

Compose now supports:

services: api: image: node environment: - PORT=${PORT}

.env is NOT for secrets in production

Store ONLY non-sensitive things like:

  • Ports

  • Project names

  • ENABLE_FEATURE flags


4️⃣ The Danger: ENV Vars Are Visible Everywhere

Secrets passed via environment variables can be exposed through:

  • docker inspect

  • docker history

  • Or worse — logs

Example:

docker inspect container

Leaks:

"Env": [ "DB_PASS=supersecret" ]

❌ Never store passwords, API keys, tokens in:

  • Dockerfile

  • .env committed to Git

  • Compose environment block (unless dev)


5️⃣ Introducing Docker Secrets (Production-Grade)

Docker Secrets store sensitive data:

✔ Encrypted
✔ Not visible via docker inspect
✔ In-memory only
✔ Mounted as temporary files
✔ Designed for Swarm, but usable with replacements for non-swarm setups

Secrets are not environment variables.
They are files mounted inside /run/secrets/.


6️⃣ Docker Swarm Secrets (Official)

Step 1: Create a secret

echo "mystrongpassword" | docker secret create db_pass -

Step 2: Attach secret to service

docker service create \ --name mydb \ --secret db_pass \ postgres

Inside the container:

/run/secrets/db_pass

You read it in your code as a file, not ENV var.


7️⃣ Hands-On Lab — Node.js App Using Docker Secrets

Step 1: Create the secret

echo "supersecret123" | docker secret create mongo_pass -

Step 2: Create service

docker service create \ --name api \ --secret mongo_pass \ node-app

Step 3: Inside your app, read:

Node.js example:

const fs = require("fs"); const password = fs.readFileSync("/run/secrets/mongo_pass", "utf8").trim();


8️⃣ Using Secrets Without Swarm (Production Hack)

Most companies using Docker without Swarm use:

  • Kubernetes Secrets

  • Vault

  • Doppler

  • AWS SSM Parameter Store

  • GCP Secret Manager

But you can emulate secrets in Docker Compose using:

Option 1 — Mount secrets as files

Create folder:

secrets/ db_pass.txt

Compose:

services: api: image: node-app volumes: - ./secrets/db_pass.txt:/run/secrets/db_pass:ro

Option 2 — Use Docker Compose Secrets (v3.7+)

secrets: db_pass: file: ./secrets/db_pass.txt services: api: image: node-app secrets: - db_pass

Works even without Swarm (Compose v2.20+).


9️⃣ Preventing Secrets From Leaking (Best Practices)

✔ Avoid secrets inside Dockerfile

Bad:

ENV DB_PASS=12345

Leaks via:

  • docker history

  • docker inspect

Good:

Pass at runtime only.


✔ Use .dockerignore

Add:

.env secrets/

To prevent accidental Git leaks.


✔ Use runtime secret files

Apps should load secrets like:

cat /run/secrets/db_pass

Not env vars.


✔ Never commit plain .env to Git

Instead commit:

.env.example

Containing:

DB_USER= DB_PASS= PORT=3000


🔒 Super-Secure Pattern (Used in Fortune 500)

Use:

ENV VAR → points to secret path APP reads secret file

Example:

environment: SECRET_PATH=/run/secrets/api_key secrets: - api_key

App loads:

fs.readFileSync(process.env.SECRET_PATH)

Result:
✔ Secret not stored in env
✔ Secret not visible in container metadata
✔ Only your app can access it


🧪 Hands-On Labs (Practice Projects)

Lab A — Compose App With Env Vars (Dev)

docker-compose.yml

services: web: image: node:18 working_dir: /app volumes: - ./app:/app environment: PORT: ${PORT} GREETING: ${GREETING}

.env

PORT=3000 GREETING=Hello from Docker

Run:

docker compose up

Visit:
http://localhost:3000


Lab B — Compose App With Secrets (Prod)

Folder:

secrets/ api_key.txt

docker-compose.yml

services: api: image: node-app secrets: - api_key secrets: api_key: file: ./secrets/api_key.txt

Run:

docker compose up

Inside container:

cat /run/secrets/api_key


👨‍💼 Interview Questions (With Answers)

❓1. Why are environment variables dangerous for secrets?

Because they show up in:

  • docker inspect

  • process list

  • logs

  • crash reports


❓2. How do Docker Secrets differ from env vars?

Feature ENV Vars Docker Secrets
Visibility Visible via inspect Hidden
Security Low High
Storage In container metadata In encrypted secret store
Access Key=value File under /run/secrets

❓3. Can you use Docker Secrets without Swarm?

YES — using:

  • Docker Compose secrets (v3.7+)

  • Mounted secret files


❓4. How do you prevent leaking .env?

Add it to .gitignore and .dockerignore.


❓5. Should you store secrets in Docker images?

NEVER.
Use runtime injection only.


🏁 Final Summary

You now know:

  • .env files

  • Passing env vars correctly

  • Secret management

  • Production-safe patterns

  • Docker Secrets (Swarm + Compose)

  • Hands-on labs

  • Interview answers

This is everything required for backend + DevOps interviews.

21. Using Configs

configs:

nginx_conf:

file: ./nginx.conf