# ═══════════════════════════════════════════════════════ # Jool International — Docker Compose PRODUCTION # Stack : PostgreSQL 16 · Django/Gunicorn · Caddy 2 # Usage : docker compose -f docker-compose.prod.yml up -d --build # ═══════════════════════════════════════════════════════ services: # ── Base de données PostgreSQL ────────────────────────── db: image: postgres:16-alpine restart: always volumes: - postgres_data:/var/lib/postgresql/data env_file: .env.prod healthcheck: test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"] interval: 10s timeout: 5s retries: 5 # ── Application Django (Gunicorn) ─────────────────────── web: build: . restart: always env_file: .env.prod volumes: - static_volume:/app/staticfiles - media_volume:/app/media depends_on: db: condition: service_healthy command: > sh -c "python manage.py collectstatic --noinput && python manage.py migrate --noinput && python manage.py compilemessages --locale=en && gunicorn config.wsgi:application --bind 0.0.0.0:8000 --workers 3 --timeout 60 --max-requests 1000 --max-requests-jitter 100 --access-logfile - --error-logfile -" # ── Caddy (reverse proxy + HTTPS automatique) ─────────── caddy: image: caddy:2-alpine restart: always ports: - "80:80" - "443:443" - "443:443/udp" # HTTP/3 / QUIC volumes: - ./Caddyfile:/etc/caddy/Caddyfile:ro - static_volume:/app/staticfiles:ro - media_volume:/app/media:ro - caddy_data:/data # certificats Let's Encrypt (persistants) - caddy_config:/config # état interne Caddy depends_on: - web volumes: postgres_data: static_volume: media_volume: caddy_data: caddy_config: