version: '3.8' x-backend-env: &backend-env DATABASE_URL: postgresql+asyncpg://pounce:${DB_PASSWORD:-changeme}@db:5432/pounce SECRET_KEY: ${SECRET_KEY:-change-this-in-production} ENVIRONMENT: ${ENVIRONMENT:-production} SITE_URL: ${SITE_URL:-} ALLOWED_ORIGINS: ${ALLOWED_ORIGINS:-} COOKIE_DOMAIN: ${COOKIE_DOMAIN:-} COOKIE_SECURE: ${COOKIE_SECURE:-true} # Optional: SMTP (email alerts) SMTP_HOST: ${SMTP_HOST:-} SMTP_PORT: ${SMTP_PORT:-587} SMTP_USER: ${SMTP_USER:-} SMTP_PASSWORD: ${SMTP_PASSWORD:-} SMTP_FROM_EMAIL: ${SMTP_FROM_EMAIL:-} SMTP_FROM_NAME: ${SMTP_FROM_NAME:-pounce} SMTP_USE_TLS: ${SMTP_USE_TLS:-true} SMTP_USE_SSL: ${SMTP_USE_SSL:-false} CONTACT_EMAIL: ${CONTACT_EMAIL:-} # Optional: OAuth GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID:-} GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET:-} GOOGLE_REDIRECT_URI: ${GOOGLE_REDIRECT_URI:-} GITHUB_CLIENT_ID: ${GITHUB_CLIENT_ID:-} GITHUB_CLIENT_SECRET: ${GITHUB_CLIENT_SECRET:-} GITHUB_REDIRECT_URI: ${GITHUB_REDIRECT_URI:-} # Optional: Stripe STRIPE_SECRET_KEY: ${STRIPE_SECRET_KEY:-} STRIPE_WEBHOOK_SECRET: ${STRIPE_WEBHOOK_SECRET:-} STRIPE_PRICE_TRADER: ${STRIPE_PRICE_TRADER:-} STRIPE_PRICE_TYCOON: ${STRIPE_PRICE_TYCOON:-} # Optional integrations DROPCATCH_CLIENT_ID: ${DROPCATCH_CLIENT_ID:-} DROPCATCH_CLIENT_SECRET: ${DROPCATCH_CLIENT_SECRET:-} DROPCATCH_API_BASE: ${DROPCATCH_API_BASE:-https://api.dropcatch.com} SEDO_PARTNER_ID: ${SEDO_PARTNER_ID:-} SEDO_SIGN_KEY: ${SEDO_SIGN_KEY:-} SEDO_API_BASE: ${SEDO_API_BASE:-https://api.sedo.com/api/v1/} MOZ_ACCESS_ID: ${MOZ_ACCESS_ID:-} MOZ_SECRET_KEY: ${MOZ_SECRET_KEY:-} services: # PostgreSQL Database db: image: postgres:16-alpine container_name: pounce-db restart: unless-stopped environment: POSTGRES_USER: pounce POSTGRES_PASSWORD: ${DB_PASSWORD:-changeme} POSTGRES_DB: pounce volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U pounce"] interval: 10s timeout: 5s retries: 5 # Redis (job queue + rate limiting storage) redis: image: redis:7-alpine container_name: pounce-redis restart: unless-stopped command: ["redis-server", "--appendonly", "yes"] volumes: - redis_data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 # FastAPI Backend backend: build: context: ./backend dockerfile: Dockerfile container_name: pounce-backend restart: unless-stopped ports: - "8000:8000" environment: <<: *backend-env ENABLE_SCHEDULER: "false" ENABLE_JOB_QUEUE: "true" REDIS_URL: redis://redis:6379/0 RATE_LIMIT_STORAGE_URI: redis://redis:6379/0 ENABLE_METRICS: "true" depends_on: db: condition: service_healthy redis: condition: service_healthy healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/health"] interval: 30s timeout: 10s retries: 3 # Scheduler (APScheduler) - runs background jobs in a separate process scheduler: build: context: ./backend dockerfile: Dockerfile container_name: pounce-scheduler restart: unless-stopped environment: <<: *backend-env ENABLE_SCHEDULER: "true" depends_on: db: condition: service_healthy command: ["python", "run_scheduler.py"] # Worker (ARQ / Redis job queue) worker: build: context: ./backend dockerfile: Dockerfile container_name: pounce-worker restart: unless-stopped environment: <<: *backend-env ENABLE_SCHEDULER: "false" ENABLE_JOB_QUEUE: "true" REDIS_URL: redis://redis:6379/0 depends_on: db: condition: service_healthy redis: condition: service_healthy command: ["arq", "app.jobs.worker.WorkerSettings"] # Next.js Frontend frontend: build: context: ./frontend dockerfile: Dockerfile container_name: pounce-frontend restart: unless-stopped ports: - "3000:3000" environment: # Internal backend URL for server-side requests BACKEND_URL: http://backend:8000 depends_on: - backend volumes: postgres_data: redis_data: