Files
xiaoxia-saas/docs/DEPLOYMENT.md
T
xiaoxia 4ed906e5fa
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 1s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 4s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 16s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 46s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 56s
CI/CD Pipeline / Build Staging API Image (push) Successful in 35s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 20s
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 57s
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 26s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m46s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m10s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m29s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (push) Successful in 4m50s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 2m2s
CI/CD Pipeline / Validate - Style (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
CI/CD Pipeline / Validate - Security (push) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
fix(staging): use stable :dev tag for containers to enable Watchtower auto-update (#2121)
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
2026-10-01 12:20:06 +08:00

168 lines
7.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 部署说明
## 唯一部署入口
小虾 SaaS 当前唯一有效 Docker 部署入口是:
- `infra/docker/compose.yml`
- `infra/docker/api.Dockerfile`
- `infra/docker/worker.Dockerfile`
- `infra/docker/web.Dockerfile`
- `infra/docker/deploy-staging.sh`
- `infra/docker/infra-production.yml`(production DB/Redis 独立基础设施)
仓库根目录的 `Dockerfile` 和 `docker-compose.yml` 已废弃,只作为防误用哨兵保留,不允许用于部署。
---
## 环境加载规则
### 开发环境
- 默认读取 `.env`
- 没有 `.env` 时回退到代码默认值
### Staging
- 服务器环境文件:`/var/lib/xiaoxia-saas-staging/.env`
- `APP_ENV=staging`
- `WEB_PORT=3001`
- 由 Gitea Actions 调用 `infra/docker/deploy-staging.sh`
### Production
- 生产环境文件:`/var/lib/xiaoxia-saas-production/.env`
- `APP_ENV=production`
- Production DB/Redis 独立于 staging:`xiaoxia-postgres-production:5432`、`xiaoxia-redis-production:6379`
- 宿主端口:Postgres `5433`、Redis `6380`、API `8001`、Web `3002`
- 只允许通过 tag/release 触发生产应用部署
- API/Worker 必须来自专用构建机或 CI 产出的 runtime image tar:`/var/lib/xiaoxia-saas-production/runtime-images-<tag>.tar`
- Web 必须来自专用构建机或 CI 产出的 prebuilt dist/release artifact,不允许在业务服务器执行前端构建
- 生产机只能接收产物、解压 release artifact、`docker load` runtime image tar、执行迁移、重启容器和健康检查
- 禁止在生产机上构建 API/Worker/Web 镜像;当前生产机资源有限且承载业务服务,不是构建机
- 必须替换所有密钥和 `CHANGE_ME` 项
---
## 本地/手动部署
从仓库根目录执行:
```bash
docker compose -f infra/docker/compose.yml up -d --build
```
Staging 手动部署应复用同一入口:
```bash
cp /var/lib/xiaoxia-saas-staging/.env .env
WEB_PORT=3001 docker compose -f infra/docker/compose.yml up -d --build
```
服务器自动部署使用:
```bash
infra/docker/deploy-staging.sh
```
部署脚本会在服务启动前执行 Alembic:
- 已存在 `alembic_version` 时执行 `alembic upgrade head`
- 已存在业务表但缺少 `alembic_version` 时执行 `alembic stamp head && alembic upgrade head`
- 空库时执行 `alembic upgrade head`
staging 已在 2026-06-21 验证:`alembic_version = 002`,健康检查通过。
---
## 外部服务配置
认证邮件和 session 存储为配置驱动:
- `ENABLE_EMAIL_DELIVERY=false` 时使用 no-op 邮件服务,不对外发送邮件。
- `ENABLE_EMAIL_DELIVERY=true` 时必须配置 `SMTP_HOST`、`SMTP_PORT`、`SMTP_USER`、`SMTP_PASSWORD`、`SMTP_FROM_EMAIL`、`SMTP_FROM_NAME`、`SMTP_USE_TLS`。
- `ENABLE_REDIS_SESSIONS=false` 时登录不会写 Redis session,JWT 仍可用于当前认证链路。
- `ENABLE_REDIS_SESSIONS=true` 时通过 `REDIS_URL` 创建 Redis session store。
Staging 当前可以保持 no-op;Production 开启前必须先验证 SMTP/Redis 连接和密钥。
---
## 生成文件存储与保留
- Staging 未配置 OSS 凭证时,生成视频落盘到 `/var/lib/xiaoxia-saas-staging/generated`,并通过 Nginx `/generated-files/` 公开访问。
- Docker volume host path 由 `GENERATED_FILES_HOST_DIR` 控制,默认仅适用于 staging:`/var/lib/xiaoxia-saas-staging/generated`。
- Production 优先使用 OSS;若临时启用本地 fallback,必须配置独立持久化目录、Nginx 只读公开路径和磁盘告警。
- OSS lifecycle rule 必须在生产 bucket 上配置并记录 rule id:临时/失败任务产物建议 7 天删除;订单/购买关联产物由业务保留策略单独保护。
- 保留策略建议:staging 生成文件保留 7 天或保留最近 20GB;production 按业务套餐/订单状态定义,禁止无上限增长。
- 清理脚本上线前必须先 dry-run 输出待删列表,再按 workspace/project 维度删除,避免误删仍被 GeneratedVideo 记录引用的文件。
- 当前脚本:`python scripts/cleanup_generated_files.py --dir /var/lib/xiaoxia-saas-staging/generated --days 7` 仅 dry-run;确认后再加 `--apply`。
---
## 生产发布清单
生产发布前必须按 `docs/PRODUCTION-RELEASE-CHECKLIST.md` 执行:先备份,后 Alembic,最后 smoke;禁止靠临场记忆操作数据库。
---
## Staging 服务器 Docker 凭证配置
Staging 服务器(116.62.226.203)需要配置 ACR 和 Gitea Registry 凭证,否则 docker pull 和 Watchtower 自动更新会失败。
### 凭证文件位置
- Docker 配置文件:`/root/.docker/config.json`
- 包含两个 registry 的认证信息:
- `xiaoxia-registry.cn-hangzhou.cr.aliyuncs.com`(阿里云 ACR)
- `git.xiaoxiajianji.com`(Gitea 容器镜像仓库)
### 服务器迁移后恢复步骤
```bash
# 1. 登录 ACR
docker login xiaoxia-registry.cn-hangzhou.cr.aliyuncs.com -u <ACR_USERNAME>
# 2. 登录 Gitea Registry
docker login git.xiaoxiajianji.com -u xiaoxia -p <GITEA_REGISTRY_TOKEN>
# 3. 重启 Watchtower(确保挂载最新 config.json)
docker restart watchtower
```
### Watchtower 配置
- 容器名:`watchtower`
- 检查间隔:300 秒(5 分钟)
- 监控容器:`xiaoxia-api-staging`、`xiaoxia-worker-staging`、`xiaoxia-web-staging`
- 必须挂载 `-v /root/.docker/config.json:/config.json` 才能拉取私有镜像
- 必须挂载 `-v /var/run/docker.sock:/var/run/docker.sock` 才能管理容器
- 容器使用 `:dev` 稳定 tag,Watchtower 通过检测 `:dev` tag 的 digest 变化来发现更新
### 镜像 Tag 策略
- CI 每次构建推送三种 tag:`${GITHUB_SHA}`(精确版本)、`${GITHUB_REF_NAME}`(分支名)、`:dev`(滚动 tag,仅 develop 分支)
- Staging 容器统一使用 `:dev` tag 启动,确保 Watchtower 能自动发现新版本
- Migration(alembic)使用 commit SHA tag 执行,不依赖 Watchtower
---
## Gitea Actions 约定
- `develop` 分支触发 staging 部署。
- tag `v*` 才允许触发 production 部署。
- Actions 先同步代码到 `/var/lib/xiaoxia-saas-staging/repo`。
- Actions 再复制 `/var/lib/xiaoxia-saas-staging/.env` 到部署工作目录。
- Actions 最终调用 `infra/docker/deploy-staging.sh`。
- Production tag deploy 会传入 `RELEASE_VERSION=${GITHUB_REF_NAME}`。
- Production deploy 必须先上传 runtime image tar;缺少 tar 时 `infra/docker/deploy-production.sh` 必须失败,防止代码已更新但 API/Worker 仍运行旧镜像。
- API/Worker runtime image tar 构建命令:`scripts/build_release_images.sh <tag>`。
- runtime image tar 生产部署入口:`scripts/deploy_release_images_production.sh <tag> <tar>` 或由 tag deploy 调用 `infra/docker/deploy-production.sh` 加载 `/var/lib/xiaoxia-saas-production/runtime-images-<tag>.tar`。
---
## 注意事项
- 不要使用根目录 `Dockerfile`。
- 不要使用根目录 `docker-compose.yml`。
- `.env.production` 不要提交真实密钥。
- OSS、数据库、Redis、JWT 密钥必须通过服务器环境文件注入。
- 生产环境必须设置 `DEBUG=false`。
- staging / production 不允许开启 `AUTO_CREATE_SCHEMA` 绕过 Alembic。
- 生产机禁止构建 API/Worker runtime 镜像;如发现需要构建,先补构建机/CI 产物流程,不得临时开启生产构建。
- `scripts/build_release_images.sh` 会检测生产容器;如果当前机器运行生产服务,默认拒绝构建 runtime 镜像。