version: '3.8' services: # ================================================================= # PostgreSQL Database Service # ================================================================= postgres: image: postgres:16-alpine container_name: keepitgoing-db restart: unless-stopped environment: POSTGRES_DB: ${DB_NAME:-keepitgoing} POSTGRES_USER: ${DB_USER:-keepitgoing} POSTGRES_PASSWORD: ${DB_PASSWORD} volumes: - db_data:/var/lib/postgresql/data networks: - backend healthcheck: test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-keepitgoing}"] interval: 10s timeout: 5s retries: 5 start_period: 30s # ================================================================= # Redis Service - Message broker for Celery # ================================================================= redis: image: redis:7-alpine container_name: keepitgoing-redis restart: unless-stopped command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru volumes: - redis_data:/data networks: - backend healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 # ================================================================= # Django/Gunicorn Web Service # ================================================================= web: build: context: . dockerfile: Dockerfile container_name: keepitgoing-web restart: unless-stopped environment: # Django Settings DJANGO_SETTINGS_MODULE: config.settings.selfhosted SECRET_KEY: ${SECRET_KEY} DEBUG: ${DEBUG:-False} ALLOWED_HOSTS: ${ALLOWED_HOSTS:-localhost} # Security CSRF_TRUSTED_ORIGINS: ${CSRF_TRUSTED_ORIGINS:-http://localhost:8000} CORS_ALLOWED_ORIGINS: ${CORS_ALLOWED_ORIGINS:-http://localhost:8000} # Database DATABASE_URL: postgresql://${DB_USER:-keepitgoing}:${DB_PASSWORD}@postgres:5432/${DB_NAME:-keepitgoing} # Redis/Celery REDIS_URL: redis://redis:6379/0 # Email EMAIL_HOST: ${EMAIL_HOST:-} EMAIL_PORT: ${EMAIL_PORT:-587} EMAIL_HOST_USER: ${EMAIL_HOST_USER:-} EMAIL_HOST_PASSWORD: ${EMAIL_HOST_PASSWORD:-} EMAIL_USE_TLS: ${EMAIL_USE_TLS:-True} DEFAULT_FROM_EMAIL: ${DEFAULT_FROM_EMAIL:-noreply@localhost} # Gunicorn GUNICORN_WORKERS: ${GUNICORN_WORKERS:-3} GUNICORN_TIMEOUT: ${GUNICORN_TIMEOUT:-60} volumes: - ./media:/app/media - static_files:/app/staticfiles ports: - "${WEB_PORT:-8000}:8000" networks: - frontend - backend depends_on: postgres: condition: service_healthy redis: condition: service_healthy healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/api/"] interval: 30s timeout: 10s retries: 3 start_period: 40s # ================================================================= # Celery Worker Service - Background task processor # ================================================================= celery-worker: build: context: . dockerfile: Dockerfile container_name: keepitgoing-celery-worker restart: unless-stopped environment: DJANGO_SETTINGS_MODULE: config.settings.selfhosted SECRET_KEY: ${SECRET_KEY} DATABASE_URL: postgresql://${DB_USER:-keepitgoing}:${DB_PASSWORD}@postgres:5432/${DB_NAME:-keepitgoing} REDIS_URL: redis://redis:6379/0 EMAIL_HOST: ${EMAIL_HOST:-} EMAIL_PORT: ${EMAIL_PORT:-587} EMAIL_HOST_USER: ${EMAIL_HOST_USER:-} EMAIL_HOST_PASSWORD: ${EMAIL_HOST_PASSWORD:-} EMAIL_USE_TLS: ${EMAIL_USE_TLS:-True} DEFAULT_FROM_EMAIL: ${DEFAULT_FROM_EMAIL:-noreply@localhost} networks: - backend depends_on: postgres: condition: service_healthy redis: condition: service_healthy command: celery-worker healthcheck: test: ["CMD-SHELL", "ps aux | grep -v grep | grep 'celery.*worker' || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 30s # ================================================================= # Celery Beat Service - Scheduled task scheduler # ================================================================= celery-beat: build: context: . dockerfile: Dockerfile container_name: keepitgoing-celery-beat restart: unless-stopped environment: DJANGO_SETTINGS_MODULE: config.settings.selfhosted SECRET_KEY: ${SECRET_KEY} DATABASE_URL: postgresql://${DB_USER:-keepitgoing}:${DB_PASSWORD}@postgres:5432/${DB_NAME:-keepitgoing} REDIS_URL: redis://redis:6379/0 EMAIL_HOST: ${EMAIL_HOST:-} EMAIL_PORT: ${EMAIL_PORT:-587} EMAIL_HOST_USER: ${EMAIL_HOST_USER:-} EMAIL_HOST_PASSWORD: ${EMAIL_HOST_PASSWORD:-} EMAIL_USE_TLS: ${EMAIL_USE_TLS:-True} DEFAULT_FROM_EMAIL: ${DEFAULT_FROM_EMAIL:-noreply@localhost} networks: - backend depends_on: postgres: condition: service_healthy redis: condition: service_healthy command: celery-beat healthcheck: test: ["CMD-SHELL", "ps aux | grep -v grep | grep 'celery.*beat' || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 40s # ================================================================= # Named Volumes # ================================================================= volumes: db_data: name: keepitgoing_db_data redis_data: name: keepitgoing_redis_data static_files: name: keepitgoing_static_files # ================================================================= # Networks # ================================================================= networks: frontend: name: keepitgoing_frontend backend: name: keepitgoing_backend