services: postgres: image: postgres:16-alpine container_name: grad-postgres restart: unless-stopped environment: POSTGRES_USER: grad POSTGRES_PASSWORD: grad POSTGRES_DB: grad volumes: - postgres-data:/var/lib/postgresql/data ports: - "5433:5432" healthcheck: test: ["CMD-SHELL", "pg_isready -U grad"] interval: 5s timeout: 3s retries: 10 qdrant: image: qdrant/qdrant:v1.16.1 container_name: grad-qdrant restart: unless-stopped volumes: - qdrant-storage:/qdrant/storage ports: - "6333:6333" - "6334:6334" healthcheck: test: ["CMD-SHELL", "bash -c '/dev/null || exit 1"] interval: 5s timeout: 3s retries: 10 start_period: 5s redis: image: redis:7-alpine container_name: grad-redis restart: unless-stopped command: ["redis-server", "--appendonly", "yes"] volumes: - redis-data:/data ports: - "6380:6379" healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 3s retries: 10 # NOTE: Ollama runs on the HOST (not in compose) because the host # already has the binary + 76 GB of pulled models at ~/.ollama. # The backend reaches it via host.docker.internal — see extra_hosts below. # If you don't have host Ollama, start the compose variant documented # in README.md under "Ollama: compose variant". backend: build: context: ./backend dockerfile: Dockerfile container_name: grad-backend restart: unless-stopped env_file: .env environment: DATABASE_URL: postgresql+asyncpg://grad:grad@postgres:5432/grad REDIS_URL: redis://redis:6379/0 QDRANT_URL: http://qdrant:6333 FRONTEND_ORIGIN: http://localhost:3000 ports: - "8010:8000" depends_on: postgres: { condition: service_healthy } qdrant: { condition: service_healthy } redis: { condition: service_healthy } extra_hosts: - "host.docker.internal:host-gateway" celery-worker: build: context: ./backend dockerfile: Dockerfile container_name: grad-celery-worker restart: unless-stopped command: ["celery", "-A", "ingestion.celery_app.celery_app", "worker", "--loglevel=INFO"] env_file: .env environment: DATABASE_URL: postgresql+asyncpg://grad:grad@postgres:5432/grad REDIS_URL: redis://redis:6379/0 QDRANT_URL: http://qdrant:6333 depends_on: redis: { condition: service_healthy } extra_hosts: - "host.docker.internal:host-gateway" celery-beat: build: context: ./backend dockerfile: Dockerfile container_name: grad-celery-beat restart: unless-stopped command: ["celery", "-A", "ingestion.celery_app.celery_app", "beat", "--loglevel=INFO", "--schedule=/tmp/celerybeat-schedule"] env_file: .env environment: DATABASE_URL: postgresql+asyncpg://grad:grad@postgres:5432/grad REDIS_URL: redis://redis:6379/0 depends_on: redis: { condition: service_healthy } frontend: build: context: ./frontend dockerfile: Dockerfile.dev container_name: grad-frontend restart: unless-stopped environment: NEXT_PUBLIC_API_BASE_URL: http://localhost:8010 volumes: - ./frontend:/app - /app/node_modules - /app/.next ports: - "3000:3000" depends_on: - backend volumes: postgres-data: qdrant-storage: redis-data: