On this page
Docker Compose Template
# Docker Compose Template for Local Development
#
# This file defines services for local development:
# - FastAPI application (with hot reload)
# - PostgreSQL database
# - Redis (cache and message broker)
# - Celery worker (background jobs)
#
# Usage:
# Start: docker-compose up -d
# Stop: docker-compose down
# Logs: docker-compose logs -f
# Rebuild: docker-compose up -d --build
version: '3.8'
services:
# ============================================================================
# PostgreSQL Database
# ============================================================================
db:
image: postgres:15-alpine
container_name: yourapp_db
restart: unless-stopped
# Environment variables
environment:
POSTGRES_USER: ${DB_USER:-postgres}
POSTGRES_PASSWORD: ${DB_PASSWORD:-postgres}
POSTGRES_DB: ${DB_NAME:-yourapp_dev}
# Performance tuning
POSTGRES_MAX_CONNECTIONS: 100
POSTGRES_SHARED_BUFFERS: 256MB
# Port mapping (PostgreSQL default: 5432)
ports:
- "${DB_PORT:-5432}:5432"
# Persist data
volumes:
- postgres_data:/var/lib/postgresql/data
# Optional: Add custom PostgreSQL config
# - ./docker/postgres/postgresql.conf:/etc/postgresql/postgresql.conf
# Health check
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-postgres}"]
interval: 10s
timeout: 5s
retries: 5
# Logging
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# ============================================================================
# Redis (Cache and Message Broker)
# ============================================================================
redis:
image: redis:7-alpine
container_name: yourapp_redis
restart: unless-stopped
# Command with persistence
command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru
# Port mapping (Redis default: 6379)
ports:
- "${REDIS_PORT:-6379}:6379"
# Persist data
volumes:
- redis_data:/data
# Health check
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
# Logging
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# ============================================================================
# FastAPI Application (Development Mode)
# ============================================================================
app:
# Build from local Dockerfile
build:
context: .
dockerfile: Dockerfile
target: development # Use development stage if multi-stage build
container_name: yourapp_api
restart: unless-stopped
# Command with hot reload
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
# Port mapping
ports:
- "${APP_PORT:-8000}:8000"
# Environment variables
environment:
# Application
ENVIRONMENT: local
DEBUG: "true"
SECRET_KEY: ${SECRET_KEY:-dev-secret-key-change-in-production}
# Database (use service name as host)
DATABASE_URL: postgresql://${DB_USER:-postgres}:${DB_PASSWORD:-postgres}@db:5432/${DB_NAME:-yourapp_dev}
DB_HOST: db
DB_PORT: 5432
DB_USER: ${DB_USER:-postgres}
DB_PASSWORD: ${DB_PASSWORD:-postgres}
DB_NAME: ${DB_NAME:-yourapp_dev}
# Redis (use service name as host)
REDIS_URL: redis://redis:6379/0
# Celery
CELERY_BROKER_URL: redis://redis:6379/0
CELERY_RESULT_BACKEND: redis://redis:6379/1
# API
API_V1_PREFIX: /api/v1
CORS_ORIGINS: '["http://localhost:3000","http://localhost:5173"]'
# External APIs (set in .env file)
SHOPIFY_API_KEY: ${SHOPIFY_API_KEY:-}
SHOPIFY_API_SECRET: ${SHOPIFY_API_SECRET:-}
# AWS (if needed)
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID:-}
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY:-}
AWS_REGION: ${AWS_REGION:-eu-west-1}
# Mount source code for hot reload
volumes:
- .:/app
# Don't override these directories
- /app/.venv
- /app/__pycache__
# Wait for database and redis
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
# Health check
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
# Logging
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# ============================================================================
# Celery Worker (Background Jobs)
# ============================================================================
worker:
# Use same image as app
build:
context: .
dockerfile: Dockerfile
target: development
container_name: yourapp_worker
restart: unless-stopped
# Command to start Celery worker
command: celery -A app.worker worker --loglevel=info --concurrency=2
# Environment variables (same as app)
environment:
ENVIRONMENT: local
DEBUG: "true"
DATABASE_URL: postgresql://${DB_USER:-postgres}:${DB_PASSWORD:-postgres}@db:5432/${DB_NAME:-yourapp_dev}
REDIS_URL: redis://redis:6379/0
CELERY_BROKER_URL: redis://redis:6379/0
CELERY_RESULT_BACKEND: redis://redis:6379/1
SECRET_KEY: ${SECRET_KEY:-dev-secret-key-change-in-production}
# External APIs
SHOPIFY_API_KEY: ${SHOPIFY_API_KEY:-}
SHOPIFY_API_SECRET: ${SHOPIFY_API_SECRET:-}
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID:-}
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY:-}
# Mount source code for hot reload
volumes:
- .:/app
- /app/.venv
# Wait for database and redis
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
# Logging
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# ============================================================================
# Celery Beat (Scheduled Tasks) - Optional
# ============================================================================
# beat:
# build:
# context: .
# dockerfile: Dockerfile
# target: development
#
# container_name: yourapp_beat
# restart: unless-stopped
#
# command: celery -A app.worker beat --loglevel=info
#
# environment:
# ENVIRONMENT: local
# CELERY_BROKER_URL: redis://redis:6379/0
# CELERY_RESULT_BACKEND: redis://redis:6379/1
#
# volumes:
# - .:/app
#
# depends_on:
# redis:
# condition: service_healthy
# ============================================================================
# Flower (Celery Monitoring) - Optional
# ============================================================================
# flower:
# build:
# context: .
# dockerfile: Dockerfile
# target: development
#
# container_name: yourapp_flower
# restart: unless-stopped
#
# command: celery -A app.worker flower --port=5555
#
# ports:
# - "5555:5555"
#
# environment:
# CELERY_BROKER_URL: redis://redis:6379/0
# CELERY_RESULT_BACKEND: redis://redis:6379/1
#
# depends_on:
# redis:
# condition: service_healthy
# ============================================================================
# Frontend (React/Vite) - Optional
# ============================================================================
# frontend:
# build:
# context: ./frontend
# dockerfile: Dockerfile.dev
#
# container_name: yourapp_frontend
# restart: unless-stopped
#
# command: npm run dev -- --host 0.0.0.0
#
# ports:
# - "5173:5173"
#
# environment:
# VITE_API_BASE_URL: http://localhost:8000
#
# volumes:
# - ./frontend:/app
# - /app/node_modules
#
# depends_on:
# - app
# ============================================================================
# MailHog (Email Testing) - Optional
# ============================================================================
# mailhog:
# image: mailhog/mailhog:latest
# container_name: yourapp_mailhog
# restart: unless-stopped
#
# ports:
# - "1025:1025" # SMTP
# - "8025:8025" # Web UI
#
# logging:
# driver: "json-file"
# options:
# max-size: "10m"
# max-file: "3"
# ==============================================================================
# VOLUMES
# ==============================================================================
volumes:
# PostgreSQL data
postgres_data:
driver: local
# Redis data
redis_data:
driver: local
# ==============================================================================
# NETWORKS (optional)
# ==============================================================================
# networks:
# default:
# name: yourapp_network
# driver: bridge
# ==============================================================================
# USAGE INSTRUCTIONS
# ==============================================================================
#
# 1. Copy this file to your project root as docker-compose.yml
#
# 2. Create .env file with your configuration:
# DB_USER=postgres
# DB_PASSWORD=postgres
# DB_NAME=yourapp_dev
# SECRET_KEY=your-secret-key
# SHOPIFY_API_KEY=your-key
# SHOPIFY_API_SECRET=your-secret
#
# 3. Start services:
# docker-compose up -d
#
# 4. View logs:
# docker-compose logs -f
# docker-compose logs -f app # Just app logs
# docker-compose logs -f worker # Just worker logs
#
# 5. Run migrations:
# docker-compose exec app alembic upgrade head
#
# 6. Access services:
# API: http://localhost:8000
# API Docs: http://localhost:8000/docs
# Database: localhost:5432
# Redis: localhost:6379
# Flower: http://localhost:5555 (if enabled)
# MailHog UI: http://localhost:8025 (if enabled)
#
# 7. Run commands in container:
# docker-compose exec app python scripts/seed_data.py
# docker-compose exec app pytest
# docker-compose exec db psql -U postgres -d yourapp_dev
#
# 8. Stop services:
# docker-compose down
#
# 9. Stop and remove volumes (WARNING: deletes data):
# docker-compose down -v
#
# 10. Rebuild after Dockerfile changes:
# docker-compose up -d --build
#
# ==============================================================================
# TROUBLESHOOTING
# ==============================================================================
#
# Port already in use:
# - Change port in .env file or docker-compose.yml
# - Or stop the conflicting service
#
# Container won't start:
# - Check logs: docker-compose logs [service_name]
# - Check health: docker-compose ps
# - Remove and recreate: docker-compose down && docker-compose up -d
#
# Database connection fails:
# - Ensure db service is healthy: docker-compose ps
# - Check DATABASE_URL matches db service credentials
# - Wait a few seconds for db to fully initialize
#
# Hot reload not working:
# - Ensure volumes are mounted correctly
# - Check file permissions
# - Try rebuilding: docker-compose up -d --build
#
# Out of disk space:
# - Clean up: docker system prune -a
# - Remove old volumes: docker volume prune