version: "3.8"

services:
  # Use `docker compose --profile backend-dev up --build --attach-dependencies` to start a database and work and the backend.

  # Use `docker compose --profile frontend-dev up --build --attach-dependencies` to start the services needed to work on the frontend. If you want to also run the inference, add a second `--profile inference` argument.

  # If you update the containers used by the inference profile, please update inference/README.md. Thank you

  # The profile ci is used by CI automations. (i.e E2E testing)

  # This DB is for the FastAPI Backend.
  db:
    platform: "${DB_PLATFORM:-}"
    image: ghcr.io/laion-ai/open-assistant/oasst-postgres
    pull_policy: always
    restart: always
    profiles: ["frontend-dev", "backend-dev", "ci", "inference-dev"]
    ports:
      - 5432:5432
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: postgres
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "postgres"]
      interval: 2s
      timeout: 2s
      retries: 10

  # Redis - caching + rate limiting on BE
  redis:
    image: redis
    restart: always
    profiles: ["frontend-dev", "backend-dev", "ci"]
    ports:
      - 6379:6379
    healthcheck:
      test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
      interval: 2s
      timeout: 2s
      retries: 10
    command: redis-server /usr/local/etc/redis/redis.conf
    volumes:
      - ./redis.conf:/usr/local/etc/redis/redis.conf
  # insights host - redis:6379
  redis-insights:
    image: redislabs/redisinsight:latest
    profiles: ["backend-dev"]
    ports:
      - 8001:8001

  # This DB is for Web Authentication and data caching.
  webdb:
    image: postgres
    restart: always
    profiles: ["frontend-dev", "ci", "inference-dev"]
    ports:
      - 5433:5432
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: oasst_web
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "postgres"]
      interval: 2s
      timeout: 2s
      retries: 10

  # This lets you manually inspect the web and backend databases.
  adminer:
    image: adminer
    restart: always
    profiles: ["frontend-dev", "backend-dev"]
    ports:
      - 8089:8080

  # This fakes an SMTP email server used by website authentication.
  # User registration emails can be found by going to localhost:1080 and
  # opening the emails listed.
  maildev:
    image: maildev/maildev
    restart: always
    profiles: ["frontend-dev", "ci"]
    environment:
      - MAILDEV_WEB_PORT=1080
      - MAILDEV_SMTP_PORT=1025
    ports:
      - "1080:1080"
      - "1025:1025"

  # The oassist backend service.
  backend:
    build:
      dockerfile: docker/Dockerfile.backend
      context: .
    image: oasst-backend
    environment:
      - POSTGRES_HOST=db
      - REDIS_HOST=redis
      - DEBUG_USE_SEED_DATA=True
      - DEBUG_ALLOW_SELF_LABELING=True
      - MAX_WORKERS=1
      - DEBUG_SKIP_TOXICITY_CALCULATION=False
      - DEBUG_SKIP_EMBEDDING_COMPUTATION=False
      - CELERY_BROKER_URL=redis://redis:6379/0
      - CELERY_RESULT_BACKEND=redis://redis:6379/0
    depends_on:
      db:
        condition: service_healthy
    profiles: ["frontend-dev", "ci", "inference-dev"]
    ports:
      - "8080:8080"

  # The oassist backend celery worker service.
  backend-worker:
    build:
      dockerfile: docker/Dockerfile.backend-worker
      context: .
    command: celery -A oasst_backend.celery_worker worker -l info -E
    image: oasst-backend-worker
    environment:
      - CELERY_BROKER_URL=redis://redis:6379/0
      - CELERY_RESULT_BACKEND=redis://redis:6379/0
      - POSTGRES_HOST=db
      - REDIS_HOST=redis
      - MAX_WORKERS=1
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    profiles: ["frontend-dev", "ci"]

  # The oassist backend celery worker service.
  backend-worker-beat:
    build:
      dockerfile: docker/Dockerfile.backend-worker
      context: .
    command: celery -A oasst_backend.celery_worker beat -l INFO
    image: oasst-backend-worker-beat
    environment:
      - CELERY_BROKER_URL=redis://redis:6379/0
      - CELERY_RESULT_BACKEND=redis://redis:6379/0
      - POSTGRES_HOST=db
      - REDIS_HOST=redis
      - MAX_WORKERS=1
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    profiles: ["frontend-dev", "ci"]

  # The oassist web service.
  web:
    build:
      dockerfile: docker/Dockerfile.website
      context: .
    image: oasst-web
    environment:
      - CLOUDFLARE_CAPTCHA_SECRET_KEY=1x0000000000000000000000000000000AA
      - CLOUDFARE_CAPTCHA_SITE_KEY=1x00000000000000000000AA
      - DATABASE_URL=postgres://postgres:postgres@webdb/oasst_web
      - FASTAPI_URL=http://backend:8080
      - FASTAPI_KEY=1234
      - NEXTAUTH_SECRET=O/M2uIbGj+lDD2oyNa8ax4jEOJqCPJzO53UbWShmq98=
      - EMAIL_SERVER_HOST=maildev
      - EMAIL_SERVER_PORT=1025
      - EMAIL_FROM=info@example.com
      - ENABLE_EMAIL_SIGNIN=true
      - ENABLE_EMAIL_SIGNIN_CAPTCHA=false
      - NEXTAUTH_URL=http://localhost:3000
      - DEBUG_LOGIN=true
      - INFERENCE_SERVER_HOST=http://inference-server:8000
      - ENABLE_CHAT=true
      - ENABLE_DRAFTS_WITH_PLUGINS=false
      - NUM_GENERATED_DRAFTS=3
    depends_on:
      webdb:
        condition: service_healthy
    ports:
      - "3000:3000"
    command: bash wait-for-postgres.sh node server.js
    profiles: ["ci"]

  # This DB is for Inference
  inference-db:
    image: postgres
    restart: always
    ports:
      - 5434:5432
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: oasst_inference
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "postgres"]
      interval: 2s
      timeout: 2s
      retries: 10
    profiles: ["inference"]

  inference-redis:
    image: redis
    restart: always
    profiles: ["inference"]
    ports:
      - 6389:6379
    healthcheck:
      test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
      interval: 2s
      timeout: 2s
      retries: 10
    command: redis-server /usr/local/etc/redis/redis.conf
    volumes:
      - ./redis.conf:/usr/local/etc/redis/redis.conf

  inference-server:
    build:
      dockerfile: docker/inference/Dockerfile.server
      context: .
      target: dev
    image: oasst-inference-server:dev
    environment:
      PORT: 8000
      REDIS_HOST: inference-redis
      POSTGRES_HOST: inference-db
      POSTGRES_DB: oasst_inference
      DEBUG_API_KEYS: "0000"
      TRUSTED_CLIENT_KEYS: "6969"
      ALLOW_DEBUG_AUTH: "True"
      API_ROOT: "http://localhost:8000"
    volumes:
      - "./oasst-shared:/opt/inference/lib/oasst-shared"
      - "./inference/server:/opt/inference/server"
    restart: unless-stopped
    ports:
      - "8000:8000"
    depends_on:
      inference-redis:
        condition: service_healthy
      inference-db:
        condition: service_healthy
    profiles: ["inference"]

  inference-worker:
    build:
      dockerfile: docker/inference/Dockerfile.worker-full
      context: .
    image: oasst-inference-worker:dev
    environment:
      API_KEY: "0000"
      MODEL_CONFIG_NAME: ${MODEL_CONFIG_NAME:-distilgpt2}
      BACKEND_URL: "ws://inference-server:8000"
      PARALLELISM: 2
    volumes:
      - "./oasst-shared:/opt/inference/lib/oasst-shared"
      - "./inference/worker:/opt/inference/worker"
    deploy:
      replicas: 1
    profiles: ["inference"]

  inference-safety:
    build:
      dockerfile: docker/inference/Dockerfile.safety
      context: .
    image: oasst-inference-safety:dev
    environment:
      PORT: 8002
    volumes:
      - "./oasst-shared:/opt/inference/lib/oasst-shared"
      - "./inference/safety:/opt/inference/safety"
    profiles: ["inference-safety"]

  prometheus:
    image: prom/prometheus
    container_name: prometheus
    command:
      - "--config.file=/etc/prometheus/prometheus.yml"
    ports:
      - 9090:9090
    restart: unless-stopped
    volumes:
      - ${PWD}/docker/prometheus:/etc/prometheus
      - prom_data:/prometheus
    profiles: ["observability"]

  grafana:
    image: grafana/grafana
    container_name: grafana
    ports:
      - 2000:2000
    restart: unless-stopped
    environment:
      - GF_SECURITY_ADMIN_USER=admin
      - GF_SECURITY_ADMIN_PASSWORD=grafana
      - GF_SERVER_HTTP_PORT=2000
    volumes:
      - ${PWD}/docker/grafana/datasources:/etc/grafana/provisioning/datasources
      - ${PWD}/docker/grafana/dashboards/dashboard.yaml:/etc/grafana/provisioning/dashboards/main.yaml
      - ${PWD}/docker/grafana/dashboards:/var/lib/grafana/dashboards
    profiles: ["observability"]

  netdata:
    image: netdata/netdata
    container_name: netdata
    pid: host
    hostname: oasst-netdata
    ports:
      - 19999:19999
    restart: unless-stopped
    cap_add:
      - SYS_PTRACE
      - SYS_ADMIN
    security_opt:
      - apparmor:unconfined
    volumes:
      - netdataconfig:/etc/netdata
      - netdatalib:/var/lib/netdata
      - netdatacache:/var/cache/netdata
      - /etc/passwd:/host/etc/passwd:ro
      - /etc/group:/host/etc/group:ro
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro
      - /etc/os-release:/host/etc/os-release:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ${PWD}/docker/netdata/go.d/redis.conf:/etc/netdata/go.d/redis.conf
      - ${PWD}/docker/netdata/go.d/postgres.conf:/etc/netdata/go.d/postgres.conf
      - ${PWD}/docker/netdata/go.d/prometheus.conf:/etc/netdata/go.d/prometheus.conf
    environment:
      # useful if want to claim monitoring agents into https://www.netdata.cloud/
      # else ignore or leave blank to just use local netdata dashboards as localhost:19999
      - NETDATA_CLAIM_TOKEN=${NETDATA_CLAIM_TOKEN:-}
      - NETDATA_CLAIM_URL=https://app.netdata.cloud
    profiles: ["observability"]

volumes:
  prom_data:
  netdataconfig:
  netdatalib:
  netdatacache:
