Docker Compose Patterns: From Development to Production
Practical patterns for Docker Compose that work in both development and production environments.
February 24, 2026 · 6 min · 1253 words · Rob Washington
Table of Contents
Docker Compose started as a development tool but has grown into something usable for small production deployments. Here are patterns that make it work well in both contexts.
services:app:secrets:- db_password- api_keyenvironment:- DB_PASSWORD_FILE=/run/secrets/db_passwordsecrets:db_password:file:./secrets/db_password.txtapi_key:external:true# Created via `docker secret create`
services:app:networks:- frontend- backenddb:networks:- backend # Not exposed to frontendnginx:networks:- frontendports:- "80:80"networks:frontend:backend:internal:true# No external access
services:app:logging:driver:syslogoptions:syslog-address:"tcp://logstash:5000"tag:"myapp"# Or use Fluentdapp:logging:driver:fluentdoptions:fluentd-address:"localhost:24224"tag:"docker.{{.Name}}"
Volume permissions: Container user might not match host user
1
2
3
services:app:user:"${UID:-1000}:${GID:-1000}"
Build context too large: Use .dockerignore
Compose version confusion: Modern Compose doesn’t need version: field
DNS resolution timing: Use health checks, not sleep
Data loss on down -v: Named volumes are deleted with -v flag
Docker Compose is powerful enough for production in many cases. The key is treating your compose files like code: version them, review changes, and use environment-specific overrides to keep things clean.
📬 Get the Newsletter
Weekly insights on DevOps, automation, and CLI mastery. No spam, unsubscribe anytime.