# 生产环境 Docker Compose 配置 # 使用外部 MySQL 和 Redis 服务 # 只暴露一个端口,SSL 由外部代理处理 services: # Backend API Service api: build: context: ../backend dockerfile: Dockerfile container_name: overseas-appointment-api restart: unless-stopped expose: - "3000" environment: - NODE_ENV=production - PORT=3000 - DB_HOST=${DB_HOST} - DB_PORT=${DB_PORT:-3306} - DB_NAME=${DB_NAME} - DB_USER=${DB_USER} - DB_PASSWORD=${DB_PASSWORD} - REDIS_HOST=${REDIS_HOST} - REDIS_PORT=${REDIS_PORT:-6379} - REDIS_PASSWORD=${REDIS_PASSWORD:-} - JWT_SECRET=${JWT_SECRET} - JWT_EXPIRES_IN=${JWT_EXPIRES_IN:-7d} - JWT_REFRESH_EXPIRES_IN=${JWT_REFRESH_EXPIRES_IN:-30d} - WECHAT_APP_ID=${WECHAT_APP_ID:-} - WECHAT_APP_SECRET=${WECHAT_APP_SECRET:-} - UPLOAD_PATH=/app/uploads - MAX_FILE_SIZE=${MAX_FILE_SIZE:-5242880} - RATE_LIMIT_WINDOW=${RATE_LIMIT_WINDOW:-60000} - RATE_LIMIT_MAX=${RATE_LIMIT_MAX:-100} - LOG_LEVEL=${LOG_LEVEL:-info} volumes: - ./data/uploads:/app/uploads - ./data/logs/api:/app/logs networks: - app-network healthcheck: test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"] interval: 30s timeout: 10s retries: 3 start_period: 40s # Nginx - 托管 Admin 静态文件 + 代理 API nginx: image: nginx:alpine container_name: overseas-appointment-nginx restart: unless-stopped ports: - "${APP_PORT:-2701}:80" volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro - ./nginx/conf.d:/etc/nginx/conf.d:ro - ./admin-dist:/usr/share/nginx/html/admin:ro - ./data/logs/nginx:/var/log/nginx depends_on: - api networks: - app-network networks: app-network: driver: bridge