# 巡樓全棧一鍵啟動:Mongo + Redis + gateway + go-worker + node-worker + web(nginx)。 # 啟動:docker compose -f deploy/docker-compose.yml --env-file deploy/.env up -d --build # 或直接用 repo 根目錄的 `make up`。 name: haixun # ---- 後端三個容器(gateway / worker / init)共用同一 image 與環境變數 ---- x-backend-build: &backend-build context: .. dockerfile: deploy/Dockerfile.backend x-backend-env: &backend-env # mongo 走 service name;若密碼含特殊字元請改用 URL-encode(見 .env.example 說明)。 HAIXUN_MONGO_URI: "mongodb://${MONGO_ROOT_USER}:${MONGO_ROOT_PASSWORD}@mongo:27017/?authSource=admin" HAIXUN_MONGO_DB: "${MONGO_DATABASE}" HAIXUN_REDIS_ADDR: "redis:6379" HAIXUN_REDIS_PASSWORD: "${REDIS_PASSWORD}" HAIXUN_JWT_ACCESS_SECRET: "${HAIXUN_JWT_ACCESS_SECRET}" HAIXUN_JWT_REFRESH_SECRET: "${HAIXUN_JWT_REFRESH_SECRET}" HAIXUN_SECRETS_KEY: "${HAIXUN_SECRETS_KEY}" HAIXUN_WORKER_SECRET: "${HAIXUN_WORKER_SECRET}" TZ: "UTC" services: mongo: image: mongo:7 restart: unless-stopped ports: - "127.0.0.1:${MONGO_PORT:-27017}:27017" environment: MONGO_INITDB_ROOT_USERNAME: ${MONGO_ROOT_USER:-haixun} MONGO_INITDB_ROOT_PASSWORD: ${MONGO_ROOT_PASSWORD:?MONGO_ROOT_PASSWORD is required} MONGO_INITDB_DATABASE: ${MONGO_DATABASE:-haixun} volumes: - mongo_data:/data/db healthcheck: test: ["CMD", "mongosh", "--quiet", "--eval", "db.adminCommand('ping')"] interval: 10s timeout: 5s retries: 5 start_period: 20s redis: image: redis:7 restart: unless-stopped command: ["redis-server", "--requirepass", "${REDIS_PASSWORD:?REDIS_PASSWORD is required}", "--appendonly", "yes"] volumes: - redis_data:/data healthcheck: test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"] interval: 10s timeout: 5s retries: 5 start_period: 10s # 一次性:建索引 / 權限 catalog / role_permissions / 第一個 admin(冪等,跑完即退出)。 init: build: *backend-build image: haixun-backend:latest restart: "no" depends_on: mongo: condition: service_healthy redis: condition: service_healthy environment: <<: *backend-env INIT_ADMIN_EMAIL: "${INIT_ADMIN_EMAIL:-admin@30cm.net}" INIT_ADMIN_PASSWORD: "${INIT_ADMIN_PASSWORD:?INIT_ADMIN_PASSWORD is required}" entrypoint: ["/app/tool"] command: ["init", "-f", "/app/etc/gateway.prod.yaml"] gateway: build: *backend-build image: haixun-backend:latest restart: unless-stopped depends_on: mongo: condition: service_healthy redis: condition: service_healthy init: condition: service_completed_successfully environment: <<: *backend-env expose: - "8890" healthcheck: test: ["CMD", "wget", "-qO-", "http://127.0.0.1:8890/api/v1/health"] interval: 15s timeout: 5s retries: 5 start_period: 20s worker: build: *backend-build image: haixun-backend:latest restart: unless-stopped depends_on: mongo: condition: service_healthy redis: condition: service_healthy init: condition: service_completed_successfully environment: <<: *backend-env entrypoint: ["/app/worker"] command: ["-f", "/app/etc/gateway.worker.prod.yaml"] node-worker: build: context: .. dockerfile: deploy/Dockerfile.node-worker image: haixun-node-worker:latest restart: unless-stopped depends_on: gateway: condition: service_healthy environment: HAIXUN_BACKEND_URL: "http://gateway:8890" HAIXUN_WORKER_SECRET: "${HAIXUN_WORKER_SECRET}" TZ: "UTC" web: build: context: .. dockerfile: deploy/Dockerfile.web image: haixun-web:latest restart: unless-stopped depends_on: gateway: condition: service_healthy ports: - "${WEB_PORT:-80}:80" volumes: mongo_data: redis_data: