I've written 50+ docker-compose files. This is what they all converge to.
Every new project starts with this template. It covers 90% of use cases.
version: '3.8'
services:
app:
build: .
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://postgres:postgres@db:5432/app
- REDIS_URL=redis://cache:6379/0
depends_on:
db:
condition: service_healthy
cache:
condition: service_started
volumes:
- .:/app
restart: unless-stopped
healthcheck:
test: curl -f http://localhost:8000/health || exit 1
interval: 30s
timeout: 10s
retries: 3
db:
image: postgres:16-alpine
environment:
POSTGRES_DB: app
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: pg_isready -U postgres
interval: 5s
timeout: 5s
retries: 5
cache:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redisdata:/data
volumes:
pgdata:
redisdata:
Why this template works
1. Health checks with depends_on conditions
The app waits for Postgres to be actually ready, not just running. This fixes the #1 Docker Compose issue: "app crashes because database isn't ready yet."
2. Alpine images
postgres:16-alpine is 80MB vs 400MB for the full image. Faster pulls, smaller containers.
3. Named volumes
Data persists between restarts. No more "where did my database go?"
4. unless-stopped restart policy
Containers restart on crash but not when you explicitly stop them. The right default.
5. Port mapping
All services accessible from your host for debugging. Remove port mappings in production.
The Dockerfile that goes with it
FROM python:3.12-slim
WORKDIR /app
# Install dependencies first (cached layer)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy app code
COPY . .
EXPOSE 8000
CMD ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Variations I use
+ Worker process:
worker:
build: .
command: python -m celery -A tasks worker --loglevel=info
depends_on:
- cache
- db
+ Nginx reverse proxy:
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
depends_on:
- app
What's in YOUR docker-compose template? Any services I'm missing?
Follow me for more DevOps patterns. I maintain 77 containerized scrapers.
More from me: 10 Dev Tools I Use Daily | 77 Scrapers on a Schedule | 150+ Free APIs
Top comments (0)