Ctrl K
ComunidadGuías…

docker-compose.prod.yml

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# =============================================================================
# Rereflect — Self-Host Entrypoint (production Docker Compose)
# -----------------------------------------------------------------------------
# This is the recommended way to self-host Rereflect. It brings up the full
# stack: PostgreSQL, Redis, the FastAPI backend, the Celery worker, and the
# Next.js frontend.
#
#   cp .env.prod.example .env   # fill in secrets
#   docker compose -f docker-compose.prod.yml up -d --build
#
# Notes:
#  - All features are unlocked (SELF_HOSTED=true on the backend, set below).
#  - Runs $0 on the free local VADER pipeline by default (no LLM key needed).
#  - The `frontend` image BAKES NEXT_PUBLIC_API_URL at BUILD time. Self-hosters
#    on a real host/domain must set NEXT_PUBLIC_API_URL to their backend's
#    public URL and REBUILD the frontend:
#        docker compose -f docker-compose.prod.yml build frontend
#  - No TLS/proxy is bundled: backend is plain HTTP on :8000, frontend on :3000.
#    Put a reverse proxy (Caddy/nginx/Traefik) in front for internet exposure.
#  - landing-web (marketing site) is intentionally NOT part of this stack; it
#    is hosted separately.
#  - The opt-in transformer sentiment model (Settings -> AI) is NOT baked into
#    backend/worker images by default -- it downloads and caches on first use
#    instead. For air-gapped installs, pre-bake it at build time:
#        BAKE_SENTIMENT_MODEL=true docker compose -f docker-compose.prod.yml build backend worker
#    See docs/SELF_HOSTING.md for the offline env flags and RAM/latency notes.
# =============================================================================

services:
  # ===========================================
  # PostgreSQL Database
  # ===========================================
  postgres:
    image: postgres:16-alpine
    container_name: rereflect-postgres
    environment:
      POSTGRES_USER: ${POSTGRES_USER:-rereflect}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-rereflect_secret}
      POSTGRES_DB: ${POSTGRES_DB:-rereflect}
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-rereflect}"]
      interval: 5s
      timeout: 5s
      retries: 5
    restart: unless-stopped

  # ===========================================
  # Redis (Celery Broker)
  # ===========================================
  redis:
    image: redis:7-alpine
    container_name: rereflect-redis
    volumes:
      - redis_data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 5s
      retries: 5
    restart: unless-stopped

  # ===========================================
  # Backend API (FastAPI)
  # ===========================================
  backend:
    build:
      context: ./services
      dockerfile: backend-api/Dockerfile
      args:
        BAKE_SENTIMENT_MODEL: ${BAKE_SENTIMENT_MODEL:-false}
    container_name: rereflect-backend
    environment:
      DATABASE_URL: postgresql://${POSTGRES_USER:-rereflect}:${POSTGRES_PASSWORD:-rereflect_secret}@postgres:5432/${POSTGRES_DB:-rereflect}
      REDIS_HOST: redis
      REDIS_PORT: 6379
      JWT_SECRET: ${JWT_SECRET}
      LLM_ENCRYPTION_KEY: ${LLM_ENCRYPTION_KEY}
      CORS_ORIGINS: ${CORS_ORIGINS:-http://localhost:3000}
      ADMIN_EMAIL: ${ADMIN_EMAIL}
      ADMIN_PASSWORD: ${ADMIN_PASSWORD}
      ROOT_PATH: ${ROOT_PATH:-}
      # Shared secret for the worker's internal health-recompute call. Empty ->
      # the internal endpoint fails closed with 503 (health scores still refresh
      # on backend-driven events).
      INTERNAL_API_SECRET: ${INTERNAL_API_SECRET:-}
      # Self-host: unlock all features, no paid tiers/limits.
      SELF_HOSTED: ${SELF_HOSTED:-true}
      # Default off -> runs on the free local VADER pipeline ($0, no key).
      ai_analysis_enabled: ${ai_analysis_enabled:-false}
      # OPTIONAL operator-owned BYOK keys (your own keys; never a Rereflect key).
      OPENAI_API_KEY: ${OPENAI_API_KEY:-}
      ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-}
      GOOGLE_AI_API_KEY: ${GOOGLE_AI_API_KEY:-}
      # OPTIONAL error tracking. Empty (default) -> Sentry is never initialized
      # and the instance sends nothing anywhere.
      SENTRY_DSN: ${SENTRY_DSN:-}
      SENTRY_ENVIRONMENT: ${SENTRY_ENVIRONMENT:-production}
      SENTRY_TRACES_SAMPLE_RATE: ${SENTRY_TRACES_SAMPLE_RATE:-0.1}
    ports:
      - "0.0.0.0:8000:8000"
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s
    restart: unless-stopped

  # ===========================================
  # Celery Worker (Background Jobs)
  # ===========================================
  worker:
    build:
      context: ./services
      dockerfile: worker-service/Dockerfile
      args:
        BAKE_SENTIMENT_MODEL: ${BAKE_SENTIMENT_MODEL:-false}
    container_name: rereflect-worker
    environment:
      DATABASE_URL: postgresql://${POSTGRES_USER:-rereflect}:${POSTGRES_PASSWORD:-rereflect_secret}@postgres:5432/${POSTGRES_DB:-rereflect}
      REDIS_HOST: redis
      REDIS_PORT: 6379
      LLM_ENCRYPTION_KEY: ${LLM_ENCRYPTION_KEY}
      SELF_HOSTED: ${SELF_HOSTED:-true}
      # Worker -> backend health recompute (GitHub #3). Both must match the
      # backend's INTERNAL_API_SECRET; the worker already depends_on backend.
      INTERNAL_API_URL: http://backend:8000
      INTERNAL_API_SECRET: ${INTERNAL_API_SECRET:-}
      ai_analysis_enabled: ${ai_analysis_enabled:-false}
      # OPTIONAL operator-owned BYOK keys (your own keys; never a Rereflect key).
      OPENAI_API_KEY: ${OPENAI_API_KEY:-}
      ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-}
      GOOGLE_AI_API_KEY: ${GOOGLE_AI_API_KEY:-}
      # OPTIONAL error tracking. Empty (default) -> Sentry is never initialized
      # and the instance sends nothing anywhere.
      SENTRY_DSN: ${SENTRY_DSN:-}
      SENTRY_ENVIRONMENT: ${SENTRY_ENVIRONMENT:-production}
      SENTRY_TRACES_SAMPLE_RATE: ${SENTRY_TRACES_SAMPLE_RATE:-0.1}
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
      backend:
        condition: service_healthy
    restart: unless-stopped

  # ===========================================
  # Frontend (Next.js)
  # ===========================================
  frontend:
    build:
    # Built from the repo root, NOT from services/frontend-web: frontend-web is a
    # pnpm workspace member, so its Dockerfile needs pnpm-workspace.yaml,
    # pnpm-lock.yaml and packages/ui. See the root .dockerignore.
      context: .
      dockerfile: services/frontend-web/Dockerfile
      args:
        NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-http://localhost:8000}
        # OPTIONAL browser-side error tracking. Empty (default) -> Sentry is never
        # initialized. NEXT_PUBLIC_* is baked in at build time, so changing this
        # requires rebuilding the frontend image.
        NEXT_PUBLIC_SENTRY_DSN: ${NEXT_PUBLIC_SENTRY_DSN:-}
        NEXT_PUBLIC_SENTRY_ENVIRONMENT: ${SENTRY_ENVIRONMENT:-production}
        NEXT_PUBLIC_SENTRY_TRACES_SAMPLE_RATE: ${SENTRY_TRACES_SAMPLE_RATE:-0.1}
    container_name: rereflect-frontend
    environment:
      NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-http://localhost:8000}
      # Server-side (Next.js node/edge runtime) error tracking. Empty -> disabled.
      SENTRY_DSN: ${SENTRY_DSN:-}
      SENTRY_ENVIRONMENT: ${SENTRY_ENVIRONMENT:-production}
      SENTRY_TRACES_SAMPLE_RATE: ${SENTRY_TRACES_SAMPLE_RATE:-0.1}
    ports:
      - "0.0.0.0:3000:3000"
    depends_on:
      - backend
    restart: unless-stopped

volumes:
  postgres_data:
  redis_data:

networks:
  default:
    name: rereflect-network