Introduction
Docker makes it easy to ship applications — but running Docker in production is a very different challenge than running it on a laptop.
In development, containers can be disposable.
In production, they must be:
- Persistent (data survives restarts)
- Isolated (services can’t see what they shouldn’t)
- Secure (secrets are not baked into images)
This article focuses on the three most common failure points when Docker moves into production:
- Volumes and persistent data
- Network isolation and service exposure
- Secrets management with Docker Compose
By the end, you’ll have battle‑tested Compose patterns you can confidently deploy.
Production vs Development Docker
AreaDevelopmentProductionDataTemporaryPersistentNetworksFlat / openIsolatedSecrets.env filesRuntime‑injectedContainersDisposableStateful patterns
📷 Suggested image:
Docker production architecture overview
Part 1: Volumes — Making Data Survive Containers
Containers are ephemeral by design. Your data should not be.
Why Volumes Matter
If a container is rebuilt: ❌ Container filesystem is lost
✅ Volume data remains intact
Common data targets:
- Databases
- Uploads / media
- Application state
- Logs
Named Volumes (Recommended)
Named volumes are managed by Docker and are ideal for production.
Example: PostgreSQL with a Named Volume
YAML
services: db: image: postgres:16 volumes: - pgdata:/var/lib/postgresql/data volumes: pgdata:
✅ Automatically persisted
✅ Easy backup and restore
✅ No hard‑coded paths
Bind Mounts (Use Sparingly)
Bind mounts map to host paths:
YAML
volumes: - /srv/app/uploads:/app/uploads
⚠️ Risks:
- Host path permissions
- Accidental deletion
- Less portable
✅ Best for:
- Large media stores
- Legacy integrations
📺 Video:
“Docker Volumes Explained for Production”
https://www.youtube.com/watch?v=p2PH_YPCsis
Part 2: Docker Networks — Isolation by Default
Docker networking is powerful — and often misunderstood.
The Golden Rule
If two containers don’t need to talk, they should not share a network.
Backend-Only Network (Internal Services)
YAML
networks: backend: internal: true YAML services: db: networks: - backend redis: networks: - backend
✅ No external access
✅ Containers can resolve by service name
✅ Clean attack surface
Public and Private Network Split
YAML
networks: frontend: backend: internal: true services: nginx: networks: - frontend - backend ports: - "443:443" app: networks: - backend
✅ Only nginx is exposed
✅ App & DB are private
✅ Clear security boundary
📷 Diagram:
Docker network segmentation diagram
📺 Video:
“Docker Networking Crash Course”
https://www.youtube.com/watch?v=bKFMS5C4CG0
Part 3: Secrets — Stop Using .env Files in Production
If secrets are inside:
docker-compose.yml.envfiles- Container images
✅ They will eventually leak.
Docker Compose Secrets (Best Practice)
Docker secrets are mounted at runtime and never baked into images.
Define a Secret
Create the secret file:
Shell
echo "supersecretpassword" > db_password.txt
Compose file:
YAML
secrets: db_password: file: ./db_password.txt
Use the Secret in a Service
YAML
services: db: image: postgres:16 secrets: - db_password environment: POSTGRES_PASSWORD_FILE: /run/secrets/db_password secrets: db_password: file: ./db_password
✅ Secret available only at runtime
✅ File permissions restricted
✅ No leakage via docker inspect
Where Secrets Appear
Inside the container:
Shell
/run/secrets/db_password
📺 Video:
“Docker Secrets Explained Simply”
https://www.youtube.com/watch?v=1CnK96GSLj0
Putting It Together: Production-Ready Compose Example
Shell
version: "3.9" services: app: image: myapp:latest networks: - backend depends_on: - db db: image: postgres:16 volumes: - pgdata:/var/lib/postgresql/data secrets: - db_password environment: POSTGRES_PASSWORD_FILE: /run/secrets/db_password networks: - backend nginx: image: nginx:alpine volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro ports: - "443:443" networks: - frontend - backend volumes: pgdata: networks: frontend: backend: internal: true secrets: db_password: file: ./db_password.txt
✅ Persistent data
✅ Network isolation
✅ Secure secrets
✅ Clean service boundaries
Common Production Mistakes
❌ Using latest images without pinning
✅ Use version tags
❌ Exposing databases via ports
✅ Use internal networks
❌ Storing secrets in Git
✅ Use Docker secrets or external vaults
❌ No backup strategy
✅ Back up volumes, not containers
When Docker Compose Is Enough (And When It Isn’t)
✅ Compose is ideal for:
- Single-host deployments
- Small clusters
- Homelabs
- Edge servers
❌ Consider Kubernetes when:
- You need auto‑scaling
- Multi‑region failover
- Complex orchestration
Compose done correctly is far more powerful than many teams realize.
Final Thoughts
Docker in production isn’t about complexity — it’s about intentional design.
If you: ✅ Treat containers as disposable
✅ Treat data as permanent
✅ Isolate aggressively
✅ Inject secrets securely
You’ll avoid 90% of real-world Docker failures.
Comments (0)
No comments yet. Be the first to leave one!
Leave a Comment