services: api: build: context: ./backend dockerfile: Dockerfile environment: DATABASE_URL: mysql+pymysql://${MYSQL_USER}:${MYSQL_PASSWORD}@mysql:3306/${MYSQL_DB} MONGO_URI: mongodb://mongo:27017/clover_trace REDIS_URL: redis://redis:6379/0 APP_ENV: production FERNET_KEY: ${FERNET_KEY} JWT_SECRET: ${JWT_SECRET} CORS_ALLOW_ORIGINS: ${CORS_ALLOW_ORIGINS} IMAGE_PROVIDER_PRIMARY: ${IMAGE_PROVIDER_PRIMARY} IMAGE_PROVIDER_FALLBACK: ${IMAGE_PROVIDER_FALLBACK} IMAGE_MODEL: ${IMAGE_MODEL} MODEL_IMAGE: ${MODEL_IMAGE} MODEL_TEXT: ${MODEL_TEXT} APIPORTS_BASE_URL: ${APIPORTS_BASE_URL} APIPORTS_KEY: ${APIPORTS_KEY} CODEPROXY_BASE_URL: ${CODEPROXY_BASE_URL} CODEPROXY_KEY: ${CODEPROXY_KEY} GEMINI_API_URL: ${GEMINI_API_URL} MAX_CONCURRENT_TASKS_PER_USER: ${MAX_CONCURRENT_TASKS_PER_USER} UPLOAD_BASE_PATH: ${UPLOAD_BASE_PATH} UPLOAD_ABS_ROOT: ${UPLOAD_ABS_ROOT} depends_on: mysql: condition: service_healthy redis: condition: service_healthy mongo: condition: service_healthy volumes: - uploads:/app/uploads expose: - "8000" command: sh -c "alembic upgrade head && uvicorn main:app --host 0.0.0.0 --port 8000 --workers ${UVICORN_WORKERS:-2}" healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/health"] interval: 30s timeout: 10s retries: 3 worker: build: context: ./backend dockerfile: Dockerfile environment: DATABASE_URL: mysql+pymysql://${MYSQL_USER}:${MYSQL_PASSWORD}@mysql:3306/${MYSQL_DB} MONGO_URI: mongodb://mongo:27017/clover_trace REDIS_URL: redis://redis:6379/0 APP_ENV: production FERNET_KEY: ${FERNET_KEY} JWT_SECRET: ${JWT_SECRET} CORS_ALLOW_ORIGINS: ${CORS_ALLOW_ORIGINS} IMAGE_PROVIDER_PRIMARY: ${IMAGE_PROVIDER_PRIMARY} IMAGE_PROVIDER_FALLBACK: ${IMAGE_PROVIDER_FALLBACK} IMAGE_MODEL: ${IMAGE_MODEL} MODEL_IMAGE: ${MODEL_IMAGE} MODEL_TEXT: ${MODEL_TEXT} APIPORTS_BASE_URL: ${APIPORTS_BASE_URL} APIPORTS_KEY: ${APIPORTS_KEY} CODEPROXY_BASE_URL: ${CODEPROXY_BASE_URL} CODEPROXY_KEY: ${CODEPROXY_KEY} GEMINI_API_URL: ${GEMINI_API_URL} MAX_CONCURRENT_TASKS_PER_USER: ${MAX_CONCURRENT_TASKS_PER_USER} UPLOAD_BASE_PATH: ${UPLOAD_BASE_PATH} UPLOAD_ABS_ROOT: ${UPLOAD_ABS_ROOT} depends_on: mysql: condition: service_healthy redis: condition: service_healthy mongo: condition: service_healthy volumes: - uploads:/app/uploads command: celery -A app.workers.celery_app worker -Q generation,packaging -c 2 -l info frontend: build: context: ./frontend dockerfile: Dockerfile args: NEXT_PUBLIC_API_BASE_URL: ${NEXT_PUBLIC_API_BASE_URL} NEXT_PUBLIC_SSE_BASE_URL: ${NEXT_PUBLIC_SSE_BASE_URL} depends_on: api: condition: service_healthy expose: - "3000" command: npm run start nginx: image: nginx:1.27-alpine depends_on: api: condition: service_healthy frontend: condition: service_started ports: - "80:80" volumes: - ./backend/nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro - uploads:/app/uploads:ro mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} MYSQL_DATABASE: ${MYSQL_DB} MYSQL_USER: ${MYSQL_USER} MYSQL_PASSWORD: ${MYSQL_PASSWORD} volumes: - mysql_data:/var/lib/mysql healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] interval: 10s timeout: 5s retries: 5 mongo: image: mongo:7.0 volumes: - mongo_data:/data/db healthcheck: test: ["CMD", "mongosh", "--quiet", "--eval", "db.adminCommand('ping').ok"] interval: 10s timeout: 5s retries: 5 redis: image: redis:7.4-alpine healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 3 volumes: mysql_data: mongo_data: uploads: