version: '3.8' services: mysql: image: mysql:8.0 container_name: zhixi-mysql restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-rootpassword} MYSQL_DATABASE: zhixi MYSQL_USER: zhixi_user MYSQL_PASSWORD: ${MYSQL_PASSWORD:-Zhixi@2026!App} ports: - '3307:3306' volumes: - mysql_data:/var/lib/mysql - ./prisma/init:/docker-entrypoint-initdb.d healthcheck: test: ['CMD', 'mysqladmin', 'ping', '-h', 'localhost'] interval: 10s timeout: 5s retries: 5 networks: - zhixi-net redis: image: redis:7-alpine container_name: zhixi-redis restart: unless-stopped ports: - '6379:6379' volumes: - redis_data:/data healthcheck: test: ['CMD', 'redis-cli', 'ping'] interval: 10s timeout: 5s retries: 5 networks: - zhixi-net api: build: context: . dockerfile: Dockerfile image: zhixi-api:latest container_name: zhixi-api restart: unless-stopped ports: - '3000:3000' environment: NODE_ENV: production PORT: '3000' DATABASE_URL: mysql://zhixi_user:${MYSQL_PASSWORD:-Zhixi@2026!App}@mysql:3306/zhixi REDIS_HOST: redis REDIS_PORT: '6379' REDIS_PASSWORD: '' REDIS_DB: '0' AI_PROVIDER: ${AI_PROVIDER:-mock} AI_DEFAULT_TIER: ${AI_DEFAULT_TIER:-primary} DEEPSEEK_API_KEY: ${DEEPSEEK_API_KEY:-} DEEPSEEK_BASE_URL: ${DEEPSEEK_BASE_URL:-https://api.deepseek.com} MINIMAX_API_KEY: ${MINIMAX_API_KEY:-} MINIMAX_BASE_URL: ${MINIMAX_BASE_URL:-https://api.minimaxi.com} JWT_SECRET: ${JWT_SECRET:-change_me_in_production} JWT_EXPIRES_IN: ${JWT_EXPIRES_IN:-1h} JWT_REFRESH_EXPIRES_IN: ${JWT_REFRESH_EXPIRES_IN:-7d} DEV_SECRET: ${DEV_SECRET:-} APPLE_BUNDLE_ID: ${APPLE_BUNDLE_ID:-cloud.longde.AIStudyApp} APPLE_ISSUER: ${APPLE_ISSUER:-https://appleid.apple.com} APPLE_JWKS_URL: ${APPLE_JWKS_URL:-https://appleid.apple.com/auth/keys} ENABLE_SWAGGER: ${ENABLE_SWAGGER:-false} SWAGGER_USER: ${SWAGGER_USER:-admin} SWAGGER_PASSWORD: ${SWAGGER_PASSWORD:-} STORAGE_DRIVER: ${STORAGE_DRIVER:-cos} STORAGE_LOCAL_PATH: ./uploads STORAGE_COS_SECRET_ID: ${STORAGE_COS_SECRET_ID:-} STORAGE_COS_SECRET_KEY: ${STORAGE_COS_SECRET_KEY:-} STORAGE_COS_BUCKET: ${STORAGE_COS_BUCKET:-} STORAGE_COS_REGION: ${STORAGE_COS_REGION:-ap-guangzhou} STORAGE_COS_DOMAIN: ${STORAGE_COS_DOMAIN:-} depends_on: mysql: condition: service_healthy redis: condition: service_healthy networks: - zhixi-net worker: build: context: . dockerfile: Dockerfile.worker image: zhixi-worker:latest container_name: zhixi-worker restart: unless-stopped environment: NODE_ENV: production DATABASE_URL: mysql://zhixi_user:${MYSQL_PASSWORD:-Zhixi@2026!App}@mysql:3306/zhixi REDIS_HOST: redis REDIS_PORT: '6379' REDIS_PASSWORD: '' REDIS_DB: '0' AI_PROVIDER: ${AI_PROVIDER:-mock} AI_DEFAULT_TIER: ${AI_DEFAULT_TIER:-primary} DEEPSEEK_API_KEY: ${DEEPSEEK_API_KEY:-} DEEPSEEK_BASE_URL: ${DEEPSEEK_BASE_URL:-https://api.deepseek.com} MINIMAX_API_KEY: ${MINIMAX_API_KEY:-} MINIMAX_BASE_URL: ${MINIMAX_BASE_URL:-https://api.minimaxi.com} JWT_SECRET: ${JWT_SECRET:-change_me_in_production} STORAGE_DRIVER: ${STORAGE_DRIVER:-cos} STORAGE_COS_SECRET_ID: ${STORAGE_COS_SECRET_ID:-} STORAGE_COS_SECRET_KEY: ${STORAGE_COS_SECRET_KEY:-} STORAGE_COS_BUCKET: ${STORAGE_COS_BUCKET:-} STORAGE_COS_REGION: ${STORAGE_COS_REGION:-ap-guangzhou} STORAGE_COS_DOMAIN: ${STORAGE_COS_DOMAIN:-} depends_on: mysql: condition: service_healthy redis: condition: service_healthy networks: - zhixi-net nginx: image: nginx:1.25-alpine container_name: zhixi-nginx restart: unless-stopped ports: - '80:80' - '443:443' volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro - ./nginx/conf.d:/etc/nginx/conf.d:ro depends_on: - api networks: - zhixi-net volumes: mysql_data: driver: local redis_data: driver: local networks: zhixi-net: driver: bridge