# =========================================== # 小虾剪辑 SaaS Docker Compose 配置 # =========================================== # # 用法: # Staging: docker compose --env-file ../../.env -f compose.yml up -d # Production: 设置相关环境变量后执行 # # 环境变量说明: # API_IMAGE - API 镜像名称 (默认: xiaoxia-saas-api:dev) # WORKER_IMAGE - Worker 镜像名称 (默认: xiaoxia-saas-worker:dev) # WEB_IMAGE - Web 镜像名称 (默认: xiaoxia-saas-web:dev) # WEB_DOCKERFILE - Web Dockerfile 路径 # WEB_NGINX_CONF - Nginx 配置文件路径 # API_PORT - API 端口映射 (staging: 8000, production: 8001) # WEB_PORT - Web 端口映射 (staging: 3001, production: 3002) # GENERATED_FILES_HOST_DIR - 生成文件的主机目录 # WORKER_CONCURRENCY - Worker 并发数 (默认: 1) # WORKER_MAX_TASKS_PER_CHILD - Worker 每个子进程最大任务数 (默认: 100) # # 重要: # - 生产环境不要挂载 web-dist volume,否则会导致 403 # - 确保环境隔离网络已创建: docker network create xiaoxia-net-${ENV} # - ENV=staging → xiaoxia-net-staging # - ENV=production → xiaoxia-net-production # # =========================================== # 日志轮转配置(所有服务共享) # =========================================== x-logging: &default-logging driver: json-file options: max-size: "50m" max-file: "3" services: # ========================================= # API 服务 # ========================================= api: image: ${API_IMAGE:-xiaoxia-saas-api:dev} # 不在生产环境构建镜像,使用预构建的镜像 # build: # context: ../.. # dockerfile: infra/docker/api.Dockerfile container_name: xiaoxia-api-${ENV:-staging} restart: unless-stopped # 环境变量文件(包含数据库密码等敏感信息) env_file: - ../../.env environment: APP_ENV: ${APP_ENV:-staging} APP_VERSION: ${APP_VERSION:-unknown} GENERATED_FILES_DIR: /app/generated GENERATED_FILES_URL_PREFIX: /generated-files PUBLIC_API_BASE_URL: ${PUBLIC_API_BASE_URL:-https://api.xiaoxiajianji.com} # 端口映射 # Staging: 8000 -> 8000 # Production: 8001 -> 8000 ports: - "127.0.0.1:${API_PORT:-8000}:8000" # 共享生成文件目录 volumes: - generated-files:/app/generated networks: - xiaoxia-net # 健康检查配置 healthcheck: test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/health', timeout=5)"] interval: 30s timeout: 10s retries: 3 start_period: 40s logging: *default-logging # ========================================= # 资源限制建议(生产环境建议启用) # ========================================= deploy: resources: limits: cpus: '2.0' memory: 2g reservations: cpus: '0.5' memory: 512M # ========================================= # Worker 服务(Celery 任务队列) # ========================================= worker: image: ${WORKER_IMAGE:-xiaoxia-saas-worker:dev} container_name: xiaoxia-worker-${ENV:-staging} restart: unless-stopped env_file: - ../../.env environment: APP_ENV: ${APP_ENV:-staging} APP_VERSION: ${APP_VERSION:-unknown} WORKER_CONCURRENCY: ${WORKER_CONCURRENCY:-1} WORKER_MAX_TASKS_PER_CHILD: ${WORKER_MAX_TASKS_PER_CHILD:-100} GENERATED_FILES_DIR: /app/generated GENERATED_FILES_URL_PREFIX: /generated-files PUBLIC_API_BASE_URL: ${PUBLIC_API_BASE_URL:-https://api.xiaoxiajianji.com} volumes: - generated-files:/app/generated networks: - xiaoxia-net # 健康检查配置 # 注:celery inspect ping 依赖 broker 连接,在容器内不可靠,改用进程检查 healthcheck: test: ["CMD-SHELL", "grep -q celery /proc/1/cmdline || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 30s logging: *default-logging # ========================================= # 资源限制建议(生产环境建议启用) # ========================================= # 注意: Worker 需要处理视频,建议分配更多资源 deploy: resources: limits: cpus: '2.0' memory: 2g reservations: cpus: '0.5' memory: 1G # ========================================= # Web 服务(Nginx + 前端静态文件) # ========================================= web: image: ${WEB_IMAGE:-xiaoxia-saas-web:dev} # 不在生产环境构建镜像,使用 web-artifact.Dockerfile # build: # context: ../.. # dockerfile: ${WEB_DOCKERFILE:-infra/docker/web.Dockerfile} # args: # NGINX_CONF: ${WEB_NGINX_CONF:-infra/docker/nginx.conf} container_name: xiaoxia-web-${ENV:-staging} restart: unless-stopped # 端口映射 # Staging: 3001 -> 80 # Production: 3002 -> 80 (通过 Nginx 反向代理) ports: - "127.0.0.1:${WEB_PORT:-3001}:80" networks: - xiaoxia-net # ========================================= # 重要: 生产环境不要添加任何 volume 挂载到 /usr/share/nginx/html # 这会导致静态文件被覆盖,返回 403 错误 # ========================================= healthcheck: test: ["CMD", "wget", "--spider", "-q", "http://127.0.0.1:80"] interval: 30s timeout: 5s retries: 3 logging: *default-logging # ========================================= # 资源限制建议 # ========================================= deploy: resources: limits: cpus: '0.5' memory: 512M # =========================================== # 共享卷配置 # =========================================== volumes: generated-files: driver: local driver_opts: type: none o: bind # 重要: 确保主机目录存在且有正确权限 # Staging: /var/lib/xiaoxia-saas-staging/generated # Production: /var/lib/xiaoxia-saas-production/generated device: ${GENERATED_FILES_HOST_DIR:-/var/lib/xiaoxia-saas-staging/generated} # =========================================== # 网络配置 # =========================================== networks: xiaoxia-net: external: true # 网络名根据 ENV 变量区分,实现 staging/production 环境隔离 # staging: xiaoxia-net-staging # production: xiaoxia-net-production name: xiaoxia-net-${ENV:-staging}