# 小虾剪辑 SaaS 部署指南

## 目录

- [环境要求](#环境要求)
- [首次部署流程](#首次部署流程)
- [版本更新流程](#版本更新流程)
- [回滚流程](#回滚流程)
- [常见问题排查](#常见问题排查)
- [环境变量说明](#环境变量说明)

---

## 环境要求

### 服务器配置

| 环境 | CPU | 内存 | 磁盘 | 说明 |
|------|-----|------|------|------|
| 生产环境 | 4 核+ | 8GB+ | 100GB+ SSD | 推荐 2 核 4GB 的独立数据库服务器 |
| 预发布环境 | 2 核 | 4GB | 50GB+ | 可与生产环境共用服务器不同端口 |

### 软件要求

- **Docker**: 24.0+
- **Docker Compose**: 2.20+
- **操作系统**: Ubuntu 22.04 LTS 或 CentOS 8+
- **网络**: 开放 80/443 端口（Web），可选开放 8000/8001（API 调试）

### 网络要求

- 服务器可访问外网（下载基础镜像）
- 数据库和 Redis 端口仅内网访问
- 域名已配置 DNS 解析

---

## 首次部署流程

### 步骤 1: 准备服务器环境

```bash
# 安装 Docker
curl -fsSL https://get.docker.com | sh

# 安装 Docker Compose
apt-get install docker-compose-plugin

# 验证安装
docker --version
docker compose version
```

### 步骤 2: 创建网络

```bash
docker network create xiaoxia-net
```

### 步骤 3: 配置环境变量

```bash
# 生产环境
cd /var/lib/xiaoxia-saas-production
cp .env.production.example .env
# 编辑 .env 文件，修改所有 CHANGE_THIS_* 的值
vim .env
```

### 步骤 4: 初始化基础设施容器

```bash
# Staging 环境
cd /var/lib/xiaoxia-saas-staging/repo/infra/docker
docker compose -f infra.yml up -d

# Production 环境
cd /var/lib/xiaoxia-saas-production/repo/infra/docker
docker compose -f infra-production.yml up -d
```

### 步骤 5: 验证基础设施

```bash
# 检查容器状态
docker ps | grep xiaoxia

# 预期输出应包含:
# xiaoxia-postgres-production
# xiaoxia-redis-production
```

### 步骤 6: 部署应用

```bash
# Staging 环境
cd /var/lib/xiaoxia-saas-staging/repo
bash infra/docker/deploy-staging.sh

# Production 环境（需要先构建镜像并上传）
bash infra/docker/deploy-production.sh
```

---

## 版本更新流程

### 方式一: CI/CD 自动部署（推荐）

#### Staging 环境
推送到 `main` 或 `develop` 分支自动触发部署。

#### Production 环境
1. 创建并推送 tag:
```bash
git tag v0.1.x
git push origin v0.1.x
```
2. CI/CD 自动完成构建和部署。

### 方式二: 手动部署

#### 步骤 1: 构建镜像（在构建服务器）

```bash
# 在构建服务器执行
git clone https://git.xiaoxiajianji.com/xiaoxia/xiaoxia-saas.git
cd xiaoxia-saas

# 构建 API 和 Worker 镜像
bash scripts/build_release_images.sh v0.1.x

# 构建 Web 镜像
docker build -f infra/docker/web-artifact.Dockerfile \
  -t xiaoxia-saas-web:v0.1.x .

# 打包镜像
docker save xiaoxia-saas-api:v0.1.x xiaoxia-saas-worker:v0.1.x \
  -o runtime-images-v0.1.x.tar
docker save xiaoxia-saas-web:v0.1.x -o web-v0.1.x.tar

# 打包源码
tar --exclude=.git --exclude=apps/web/node_modules \
  -czf release-v0.1.x.tar.gz .
```

#### 步骤 2: 上传到生产服务器

```bash
# 上传到生产服务器
scp runtime-images-v0.1.x.tar user@production:/var/lib/xiaoxia-saas-production/
scp web-v0.1.x.tar user@production:/var/lib/xiaoxia-saas-production/
scp release-v0.1.x.tar.gz user@production:/var/lib/xiaoxia-saas-production/
```

#### 步骤 3: 部署到生产环境

```bash
# 在生产服务器执行
cd /var/lib/xiaoxia-saas-production

# 加载镜像
docker load -i runtime-images-v0.1.x.tar
docker load -i web-v0.1.x.tar

# 解压源码
tar -xzf release-v0.1.x.tar.gz
cp .env .env.backup

# 执行部署
RELEASE_VERSION=v0.1.x bash repo/infra/docker/deploy-production.sh
```

#### 步骤 4: 验证部署

```bash
# 检查容器状态
docker compose -f infra/docker/compose.yml ps

# 健康检查
curl https://saas.xiaoxiajianji.com/
curl https://api.xiaoxiajianji.com/health
```

---

## 回滚流程

### 方式一: 使用回滚脚本

```bash
# 查看可用的历史版本
ls -la /var/lib/xiaoxia-saas-production/runtime-images-*.tar

# 回滚到指定版本
bash scripts/rollback.sh v0.1.x
```

### 方式二: 手动回滚

#### 步骤 1: 停止当前容器

```bash
cd /var/lib/xiaoxia-saas-production/repo/infra/docker
docker compose --env-file ../../.env down
```

#### 步骤 2: 加载旧版本镜像

```bash
cd /var/lib/xiaoxia-saas-production
docker load -i runtime-images-v0.1.y.tar
docker load -i web-v0.1.y.tar
```

#### 步骤 3: 部署旧版本

```bash
RELEASE_VERSION=v0.1.y bash repo/infra/docker/deploy-production.sh
```

#### 步骤 4: 验证回滚

```bash
# 检查版本号
curl https://api.xiaoxiajianji.com/health | jq .version

# 检查容器
docker compose -f infra/docker/compose.yml ps
```

---

## 常见问题排查

### 问题 1: Web 容器返回 403

**症状**: 访问网站返回 403 Forbidden

**原因**: web-dist volume 错误挂载

**排查**:
```bash
# 检查 web 容器日志
docker logs xiaoxia-web-production

# 检查 web 容器挂载
docker inspect xiaoxia-web-production | jq '.[0].Mounts'
```

**解决方案**:
```bash
# 确保不要在生产环境使用 volume 挂载 web-dist
# 检查 docker-compose.yml 确保没有错误的 volume 挂载
```

### 问题 2: API 健康检查失败

**症状**: API 容器不断重启

**排查**:
```bash
# 查看 API 日志
docker logs xiaoxia-api-production

# 检查数据库连接
docker exec -it xiaoxia-api-production python -c \
  "from sqlalchemy import create_engine; \
   engine = create_engine('$DATABASE_URL'); \
   print(engine.table_names())"
```

**解决方案**:
1. 确保数据库容器正常运行
2. 检查 DATABASE_URL 配置正确
3. 检查 .env 文件是否存在

### 问题 3: 镜像构建失败

**症状**: OOM 或构建超时

**排查**:
```bash
# 检查构建服务器内存
free -h

# 检查磁盘空间
df -h
```

**解决方案**:
```bash
# 添加 swap
fallocate -l 4G /swapfile
mkswap /swapfile
swapon /swapfile
```

### 问题 4: 数据库迁移失败

**症状**: 应用启动但报错缺少表

**排查**:
```bash
# 检查迁移状态
docker exec -it xiaoxia-api-production \
  sh -c 'alembic current'
```

**解决方案**:
```bash
# 手动执行迁移
docker exec -it xiaoxia-api-production \
  sh -c 'alembic upgrade head'
```

### 问题 5: Worker 不处理任务

**排查**:
```bash
# 检查 worker 日志
docker logs xiaoxia-worker-production

# 检查 Redis 连接
docker exec -it xiaoxia-redis-production redis-cli ping
```

---

## 环境变量说明

### 必需配置

| 变量名 | 说明 | 示例 |
|--------|------|------|
| `DATABASE_URL` | PostgreSQL 连接字符串 | `postgresql://user:pass@host:5432/db` |
| `REDIS_URL` | Redis 连接字符串 | `redis://:pass@host:6379/0` |
| `JWT_SECRET_KEY` | JWT 密钥（至少 32 字符） | `your-random-secret-key` |

### 应用配置

| 变量名 | 说明 | 默认值 |
|--------|------|--------|
| `APP_ENV` | 运行环境 | `staging` / `production` |
| `DEBUG` | 调试模式 | `false` |
| `LOG_LEVEL` | 日志级别 | `INFO` / `WARNING` |
| `BASE_URL` | 应用基础 URL | `https://saas.xiaoxiajianji.com` |

### 邮件配置

| 变量名 | 说明 |
|--------|------|
| `SMTP_HOST` | SMTP 服务器地址 |
| `SMTP_PORT` | SMTP 端口（587 或 465） |
| `SMTP_USER` | SMTP 用户名 |
| `SMTP_PASSWORD` | SMTP 密码 |
| `SMTP_FROM_EMAIL` | 发件人邮箱 |

### 存储配置（可选）

| 变量名 | 说明 |
|--------|------|
| `OSS_ENDPOINT` | 阿里云 OSS 端点 |
| `OSS_ACCESS_KEY_ID` | OSS Access Key |
| `OSS_ACCESS_KEY_SECRET` | OSS Secret |
| `OSS_BUCKET_NAME` | OSS Bucket 名称 |

### 部署配置

| 变量名 | 说明 | 默认值 |
|--------|------|--------|
| `API_IMAGE` | API 镜像名 | `xiaoxia-saas-api:dev` |
| `WORKER_IMAGE` | Worker 镜像名 | `xiaoxia-saas-worker:dev` |
| `WEB_IMAGE` | Web 镜像名 | `xiaoxia-saas-web:dev` |
| `WEB_PORT` | Web 端口 | `3001` (staging) / `3002` (production) |
| `API_PORT` | API 端口 | `8000` (staging) / `8001` (production) |

---

## 安全建议

1. **定期更新**: 保持 Docker 和基础镜像更新
2. **密钥管理**: 使用 Docker secrets 或外部密钥管理服务
3. **网络隔离**: 限制数据库和 Redis 端口仅内网访问
4. **日志审计**: 定期检查容器日志和系统日志
5. **备份策略**: 定期备份数据库和关键配置文件
