name: ${PROJECT_NAME} x-shared-env: &shared-env # PostgreSQL POSTGRES_SERVER: ${POSTGRES_SERVER:-db} POSTGRES_PORT: ${POSTGRES_PORT:-5432} POSTGRES_DB: ${POSTGRES_DB:-app} POSTGRES_USER: ${POSTGRES_USER:-postgres} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set in .env} # Redis REDIS_HOST: ${REDIS_HOST:-redis} REDIS_PORT: ${REDIS_PORT:-6379} REDIS_PASSWORD: ${REDIS_PASSWORD:?REDIS_PASSWORD must be set in .env} # rustfs RUSTFS_ACCESS_KEY: ${RUSTFS_ACCESS_KEY:?RUSTFS_ACCESS_KEY must be set in .env} RUSTFS_SECRET_KEY: ${RUSTFS_SECRET_KEY:?RUSTFS_SECRET_KEY must be set in .env} RUSTFS_ENDPOINT: ${RUSTFS_ENDPOINT:-http://rustfs:9000} # SMTP SMTP_HOST: ${SMTP_HOST:-mailcatcher} SMTP_USER: ${SMTP_USER:-} SMTP_PASSWORD: ${SMTP_PASSWORD:-} EMAILS_FROM_EMAIL: ${EMAILS_FROM_EMAIL:-info@example.com} SMTP_TLS: ${SMTP_TLS:-False} SMTP_SSL: ${SMTP_SSL:-False} SMTP_PORT: ${SMTP_PORT:-1025} x-backend-common: &backend-common image: "${DOCKER_IMAGE_BACKEND?Variable not set}:${TAG-latest}" build: context: ../ dockerfile: src/backend/Dockerfile network: host args: DOCKERHUB_REGISTRY: ${DOCKERHUB_REGISTRY:-} UV_INDEX_URL: ${UV_INDEX_URL:-} GITHUB_PROXY_URL: ${GITHUB_PROXY_URL:-} env_file: - .env environment: <<: *shared-env services: # ============================================================ # 基础设施服务 # ============================================================ db: image: "${DOCKERHUB_REGISTRY:-}library/postgres:18" restart: always healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] interval: 10s retries: 5 start_period: 30s timeout: 10s volumes: - ./app-data/db:/var/lib/postgresql/data/pgdata environment: PGDATA: /var/lib/postgresql/data/pgdata POSTGRES_DB: ${POSTGRES_DB:-app} POSTGRES_USER: ${POSTGRES_USER:-postgres} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set in .env} redis: image: "${DOCKERHUB_REGISTRY:-}library/redis:latest" restart: always healthcheck: test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"] interval: 10s timeout: 5s retries: 5 start_period: 10s command: redis-server --requirepass ${REDIS_PASSWORD} volumes: - ./app-data/redis/data:/data rustfs-permission-init: image: "${DOCKERHUB_REGISTRY:-}rustfs/rustfs:latest" user: "0:0" restart: "no" entrypoint: [ "sh", "-c", "mkdir -p /data /app/logs /opt/tls && chown -R 10001:10001 /data /app/logs /opt/tls", ] volumes: - ./app-data/rustfs/data/pro:/data - ./app-data/rustfs/logs:/app/logs - ./app-data/rustfs/data/certs/:/opt/tls rustfs: image: "${DOCKERHUB_REGISTRY:-}rustfs/rustfs:latest" restart: always depends_on: rustfs-permission-init: condition: service_completed_successfully security_opt: - "no-new-privileges:true" environment: - RUSTFS_VOLUMES=/data/rustfs0 - RUSTFS_ADDRESS=0.0.0.0:9000 - RUSTFS_CONSOLE_ADDRESS=0.0.0.0:9001 - RUSTFS_CONSOLE_ENABLE=true - RUSTFS_CORS_ALLOWED_ORIGINS=* - RUSTFS_CONSOLE_CORS_ALLOWED_ORIGINS=* - RUSTFS_ACCESS_KEY=${RUSTFS_ACCESS_KEY} - RUSTFS_SECRET_KEY=${RUSTFS_SECRET_KEY} - RUSTFS_OBS_LOGGER_LEVEL=info volumes: - ./app-data/rustfs/data/pro:/data - ./app-data/rustfs/logs:/app/logs - ./app-data/rustfs/data/certs/:/opt/tls healthcheck: test: [ "CMD", "sh", "-c", "curl -f http://127.0.0.1:9000/health && curl -f http://127.0.0.1:9001/rustfs/console/health", ] interval: 30s timeout: 10s retries: 3 start_period: 40s adminer: image: "${DOCKERHUB_REGISTRY:-}library/adminer:latest" restart: always profiles: ["debug"] depends_on: - db environment: - ADMINER_DESIGN=pepa-linha-dark mailcatcher: image: "${DOCKERHUB_REGISTRY:-}schickling/mailcatcher:latest" restart: always profiles: ["debug"] # ============================================================ # 应用服务 # ============================================================ prestart: <<: *backend-common depends_on: db: condition: service_healthy restart: true rustfs: condition: service_healthy task-runner: condition: service_completed_successfully command: bash scripts/prestart.sh backend: <<: *backend-common restart: always depends_on: db: condition: service_healthy restart: true redis: condition: service_healthy rustfs: condition: service_healthy prestart: condition: service_completed_successfully healthcheck: test: [ "CMD", "curl", "-f", "http://localhost:8000/api/v1/utils/health-check/", ] interval: 10s timeout: 5s retries: 5 start_period: 30s volumes: - /var/run/docker.sock:/var/run/docker.sock - ${HOST_PROJECT_HOME}:${DOCKER_PROJECT_HOME} worker: <<: *backend-common restart: always depends_on: backend: condition: service_healthy command: celery -A app.core.celery worker -Q evolution -n evo@%h --loglevel=info --concurrency=50 volumes: - /var/run/docker.sock:/var/run/docker.sock - ${HOST_PROJECT_HOME}:${DOCKER_PROJECT_HOME} research-worker: <<: *backend-common restart: always depends_on: backend: condition: service_healthy # 科研/协作 worker:只消费 research 队列,交互式任务,独立并发池 command: celery -A app.core.celery worker -Q research -n research@%h --loglevel=info --concurrency=50 volumes: - /var/run/docker.sock:/var/run/docker.sock - ${HOST_PROJECT_HOME}:${DOCKER_PROJECT_HOME} flower: <<: *backend-common restart: always depends_on: redis: condition: service_healthy worker: condition: service_started command: celery -A app.core.celery flower --port=5555 task-runner: image: "${DOCKER_IMAGE_TASK_RUNNER:-llm4ad-task-runner}:${TAG-latest}" build: context: ../ network: host dockerfile: src/backend/Dockerfile.task args: DOCKERHUB_REGISTRY: ${DOCKERHUB_REGISTRY:-} APT_MIRROR: ${APT_MIRROR:-} UV_INDEX_URL: ${UV_INDEX_URL:-} GITHUB_PROXY_URL: ${GITHUB_PROXY_URL:-} CC_SWITCH_RELEASE_BASE: ${CC_SWITCH_RELEASE_BASE:-https://github.com/SaladDay/cc-switch-cli/releases/download} OPENCODE_RELEASE_BASE: ${OPENCODE_RELEASE_BASE:-https://github.com/anomalyco/opencode/releases/download} restart: "no" entrypoint: ["true"] # ARL (Auto-DL-Loop) 镜像,按需动态创建容器 arl-worker: image: "${DOCKER_IMAGE_ARL_WORKER:-llm4ad-arl-worker}:${TAG-latest}" build: context: ../third_party/auto-dl-loop dockerfile: docker/Dockerfile target: worker network: host args: DOCKERHUB_REGISTRY: ${DOCKERHUB_REGISTRY:-} restart: "no" entrypoint: ["true"] arl-validator: image: "${DOCKER_IMAGE_ARL_VALIDATOR:-llm4ad-arl-validator}:${TAG-latest}" build: context: ../third_party/auto-dl-loop dockerfile: docker/Dockerfile target: validator network: host args: DOCKERHUB_REGISTRY: ${DOCKERHUB_REGISTRY:-} restart: "no" entrypoint: ["true"] code_server_proxy: image: "${DOCKERHUB_REGISTRY:-}library/nginx:latest" restart: always environment: - AUTH_BACKEND_URL=${AUTH_BACKEND_URL:-http://backend:8000} volumes: - ./code-server/nginx.conf:/etc/nginx/templates/default.conf.template - ./code-server/nginx.http.conf:/etc/nginx/nginx.conf frontend: image: "${DOCKER_IMAGE_FRONTEND?Variable not set}:${TAG-latest}" restart: always depends_on: backend: condition: service_healthy code_server_proxy: condition: service_started build: context: ../ network: host dockerfile: src/frontend/Dockerfile args: - DOCKERHUB_REGISTRY=${DOCKERHUB_REGISTRY:-} - VITE_API_URL= - VITE_CODE_SERVER_URL=${VITE_CODE_SERVER_URL:-/code_ide} - VITE_FOOTER_BEIAN=${VITE_FOOTER_BEIAN:-} - NODE_ENV=production volumes: - ../src/frontend/nginx-api-proxy.conf:/etc/nginx/extra-conf.d/api-proxy.conf:ro - ../src/frontend/nginx-code-ide-proxy.conf:/etc/nginx/extra-conf.d/code-ide-proxy.conf:ro ports: - "${FRONTEND_PORT:-80}:80"