Docker in Production: Volumes, Networks, and Compose Secrets

By Eddie Power Apr 1, 2026 in Containers & Virtualization 4 min read
bash ubuntu debian arch linux alpine linux docker apache nftables

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:

  1. Volumes and persistent data
  2. Network isolation and service exposure
  3. 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
  • .env files
  • 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.

Share this article

E
Eddie Power admin

Linux enthusiast and open source advocate.

Comments (0)

No comments yet. Be the first to leave one!

Leave a Comment

Comments are moderated and will appear after approval.