services: postgres: image: postgres:17-alpine environment: POSTGRES_DB: docuvault POSTGRES_USER: postgres POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} volumes: - postgres_data:/var/lib/postgresql/data - ./docker/postgres/initdb.d:/docker-entrypoint-initdb.d:ro healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres -d docuvault"] interval: 10s timeout: 5s retries: 5 start_period: 10s minio: image: minio/minio:latest command: server /data --console-address ":9001" environment: MINIO_ROOT_USER: ${MINIO_ROOT_USER} MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD} # RESEARCH.md Finding 3, T-03-09: allow browser CORS preflight for direct PUT uploads. # Use FRONTEND_URL (plain string) not CORS_ORIGINS (pydantic JSON list format). MINIO_API_CORS_ALLOW_ORIGIN: ${FRONTEND_URL:-http://localhost:5173} MINIO_SERVER_URL: http://localhost:9000 ports: - "9000:9000" - "9001:9001" volumes: - minio_data:/data healthcheck: test: ["CMD", "mc", "ready", "local"] interval: 10s timeout: 5s retries: 5 start_period: 15s redis: image: redis:7-alpine command: redis-server --requirepass ${REDIS_PASSWORD} healthcheck: test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"] interval: 10s timeout: 3s retries: 5 backend: build: ./backend ports: - "8000:8000" volumes: - ./backend:/app environment: - DATABASE_URL=${DATABASE_URL} - DATABASE_MIGRATE_URL=${DATABASE_MIGRATE_URL} - MINIO_ENDPOINT=${MINIO_ENDPOINT} - MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY} - MINIO_SECRET_KEY=${MINIO_SECRET_KEY} - MINIO_BUCKET=${MINIO_BUCKET} - MINIO_PUBLIC_ENDPOINT=${MINIO_PUBLIC_ENDPOINT:-localhost:9000} - REDIS_URL=${REDIS_URL} - SECRET_KEY=${SECRET_KEY} - ADMIN_EMAIL=${ADMIN_EMAIL} - ADMIN_PASSWORD=${ADMIN_PASSWORD} - CORS_ORIGINS=${CORS_ORIGINS:-http://localhost:5173} - FRONTEND_URL=${FRONTEND_URL:-http://localhost:5173} - PYTHONDONTWRITEBYTECODE=1 - LOG_LEVEL=${LOG_LEVEL:-INFO} - LOG_JSON=${LOG_JSON:-false} labels: logging: "promtail" extra_hosts: - "host.docker.internal:host-gateway" command: uvicorn main:app --host 0.0.0.0 --port 8000 --reload depends_on: postgres: condition: service_healthy minio: condition: service_healthy redis: condition: service_healthy celery-worker: build: ./backend environment: - DATABASE_URL=${DATABASE_URL} - MINIO_ENDPOINT=${MINIO_ENDPOINT} - MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY} - MINIO_SECRET_KEY=${MINIO_SECRET_KEY} - MINIO_BUCKET=${MINIO_BUCKET} - REDIS_URL=${REDIS_URL} - CLOUD_CREDS_KEY=${CLOUD_CREDS_KEY} - PYTHONDONTWRITEBYTECODE=1 labels: logging: "promtail" volumes: - ./backend:/app extra_hosts: - "host.docker.internal:host-gateway" command: celery -A celery_app worker --loglevel=info -Q documents depends_on: postgres: condition: service_healthy minio: condition: service_healthy redis: condition: service_healthy celery-beat: build: ./backend environment: - DATABASE_URL=${DATABASE_URL} - MINIO_ENDPOINT=${MINIO_ENDPOINT} - MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY} - MINIO_SECRET_KEY=${MINIO_SECRET_KEY} - MINIO_BUCKET=${MINIO_BUCKET} - REDIS_URL=${REDIS_URL} - PYTHONDONTWRITEBYTECODE=1 extra_hosts: - "host.docker.internal:host-gateway" command: celery -A celery_app beat --loglevel=info depends_on: postgres: condition: service_healthy minio: condition: service_healthy redis: condition: service_healthy loki: image: grafana/loki:latest ports: - "3100:3100" volumes: - ./docker/loki/loki-config.yaml:/etc/loki/local-config.yaml - loki_data:/loki command: -config.file=/etc/loki/local-config.yaml promtail: image: grafana/promtail:latest volumes: - ./docker/loki/promtail-config.yaml:/etc/promtail/config.yaml - /var/lib/docker/containers:/var/lib/docker/containers:ro - /var/run/docker.sock:/var/run/docker.sock command: -config.file=/etc/promtail/config.yaml depends_on: - loki grafana: image: grafana/grafana:latest ports: - "3000:3000" environment: - GF_AUTH_ANONYMOUS_ENABLED=true - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin volumes: - grafana_data:/var/lib/grafana depends_on: - loki frontend: build: ./frontend ports: - "5173:5173" volumes: - ./frontend/src:/app/src - ./frontend/index.html:/app/index.html depends_on: - backend command: npm run dev -- --host 0.0.0.0 volumes: postgres_data: minio_data: loki_data: grafana_data: