rtc-voice-chat/backend/DEPLOYMENT.md
2026-04-02 20:15:15 +08:00

296 lines
7.2 KiB
Markdown
Raw Permalink 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.

# 部署指南
本项目使用 Docker + docker-compose 管理多环境部署。所有配置通过环境变量注入,`load_dotenv(override=False)` 保证**真实环境变量(容器/CI/CD 注入)永远优先于 `.env` 文件**。
---
## 文件结构
```
backend/
├── Dockerfile # 多阶段构建镜像(共用)
├── docker-compose.yml # 基础配置(生产默认)
├── docker-compose.dev.yml # 开发环境 override
├── docker-compose.staging.yml # 测试环境 override
├── .env # 本地开发配置(不提交 git
├── .env.staging # 测试环境配置模板(不提交真实密钥)
└── .env.example # 全量变量说明(提交 git
```
---
## 三个环境对比
| 项目 | 开发 (dev) | 测试 (staging) | 生产 (production) |
|------|-----------|---------------|------------------|
| 启动方式 | uv 直接运行 或 Docker | docker-compose + override | Docker 镜像 + CI/CD |
| 配置来源 | `.env` | `.env.staging` | 平台注入环境变量 |
| `LOG_LEVEL` | `DEBUG` | `INFO` | `WARNING` |
| `--reload` | 是 | 否 | 否 |
| `restart` | no | unless-stopped | unless-stopped |
| `.env` 文件 | 挂载 / 读取 | 挂载 `.env.staging` | **不挂载任何文件** |
---
## 开发环境
### 方式一:直接用 uv推荐最快
```bash
cd backend
uv run uvicorn server:app --host 0.0.0.0 --port 3001 --reload
```
自动读取 `.env`,支持热重载。
### 方式二Docker + dev override
```bash
cd backend
docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build
```
源码目录挂载进容器,修改文件自动重载,行为与方式一一致,但运行在容器内。
---
## 测试环境 (Staging)
### 服务器目录约定
项目统一放在 `/opt` 下,这是 Linux 存放第三方应用的标准位置,权限独立、路径固定:
```bash
/opt/aigc-demo/ # 项目根目录
└── backend/ # Python 后端(本文档所描述的部分)
```
初次登录服务器后执行:
```bash
sudo mkdir -p /opt/aigc-demo
sudo chown $USER:$USER /opt/aigc-demo
```
### 第一步:服务器安装 Docker
```bash
# Ubuntu / Debian
curl -fsSL https://get.docker.com | sh
sudo systemctl enable --now docker
# CentOS / AlmaLinux
sudo yum install -y docker
sudo systemctl enable --now docker
# 验证
docker --version
docker compose version
```
### 第二步:拉取代码
```bash
cd /opt/aigc-demo
git clone https://github.com/your-repo/rtc-aigc-demo.git .
# 或者已有仓库时更新
git pull
```
如果服务器没有配置 git也可以从本机传
```bash
# 本机执行
scp -r ./backend user@your-server-ip:/opt/aigc-demo/
```
### 第三步:配置 staging 密钥
```bash
cd /opt/aigc-demo/backend
cp .env.staging .env.staging.local
vim .env.staging.local
```
**必填项:**
```bash
CUSTOM_ACCESS_KEY_ID=你的火山引擎AK
CUSTOM_SECRET_KEY=你的火山引擎SK
CUSTOM_RTC_APP_ID=你的RTC AppId
CUSTOM_RTC_APP_KEY=你的RTC AppKey
CUSTOM_TASK_ID=你的TaskId
CUSTOM_AGENT_USER_ID=你的AgentUserId
LOCAL_LLM_API_KEY=你的Ark API Key
LOCAL_LLM_MODEL=你的Ark端点ID
# 关键:填服务器公网 IP 或域名
CUSTOM_LLM_URL=http://你的公网IP:3001/v1/api/chat_callback
# 有域名 + HTTPS 则改为:
# CUSTOM_LLM_URL=https://your-staging-domain.example.com/v1/api/chat_callback
```
> 火山引擎 RTC 平台需要能主动回调 `CUSTOM_LLM_URL`,所以这里必须填**公网地址**localhost 无效。
### 第四步:开放防火墙端口
在云平台控制台的**安全组**放行 `3001` 端口入方向TCP
- **阿里云**`ECS 控制台 → 安全组 → 配置规则 → 添加入方向规则 → 端口 3001`
- **腾讯云**`CVM 控制台 → 安全组 → 添加规则 → 端口 3001`
### 第五步:启动服务
```bash
cd /opt/aigc-demo/backend
docker compose -f docker-compose.yml -f docker-compose.staging.yml \
--env-file .env.staging.local up -d --build
```
`-d` 后台运行,`--build` 每次重新构建镜像。
### 第六步:验证
```bash
# 容器内健康检查
curl http://localhost:3001/health
# 预期:{"status":"ok"}
# 从外网验证(换成你的公网 IP
curl http://你的公网IP:3001/health
# 查看实时日志
docker compose logs -f backend
```
### 日常运维命令
```bash
# 更新代码后重新部署
git pull
docker compose -f docker-compose.yml -f docker-compose.staging.yml \
--env-file .env.staging.local up -d --build
# 重启服务
docker compose -f docker-compose.yml -f docker-compose.staging.yml restart
# 停止服务
docker compose -f docker-compose.yml -f docker-compose.staging.yml down
# 查看最近 100 行日志
docker compose logs --tail=100 backend
```
---
## 生产环境
### 构建镜像
```bash
cd backend
# 打带版本号的 tag用 git commit hash
IMAGE_TAG=$(git rev-parse --short HEAD)
docker build -t aigc-backend:${IMAGE_TAG} .
docker build -t aigc-backend:latest .
```
### 推送到镜像仓库
```bash
# 以阿里云 ACR 为例
docker tag aigc-backend:${IMAGE_TAG} registry.cn-beijing.aliyuncs.com/your-ns/aigc-backend:${IMAGE_TAG}
docker push registry.cn-beijing.aliyuncs.com/your-ns/aigc-backend:${IMAGE_TAG}
```
### 运行
生产环境**不使用任何 `.env` 文件**所有密钥由平台ECS 环境变量、K8s Secret、Cloud Run注入
```bash
docker run -d \
--name aigc-backend \
--restart unless-stopped \
-p 3001:3001 \
-e CUSTOM_ACCESS_KEY_ID=xxx \
-e CUSTOM_SECRET_KEY=xxx \
-e LOCAL_LLM_API_KEY=xxx \
-e LOG_LEVEL=warning \
# ... 其余变量 ...
aigc-backend:${IMAGE_TAG}
```
或通过 `--env-file` 传入一个**不在代码仓库中**的生产密钥文件:
```bash
docker run -d --env-file /secure/prod.env -p 3001:3001 aigc-backend:${IMAGE_TAG}
```
---
## 负载均衡 / 反向代理注意事项
| 要求 | 原因 |
|------|------|
| idle timeout ≥ 75s | 容器 `--timeout-keep-alive 75`LB 超时需更长 |
| 关闭响应缓冲 | `/api/chat_callback` 是 SSE 流式响应Nginx 需设 `proxy_buffering off` |
| TLS 在 LB 层终止 | 容器内不处理 HTTPS |
| 健康检查路径 `GET /health` | 返回 `{"status":"ok"}`HTTP 200 |
| sticky session如需水平扩展| 会话存储在内存中,同一客户端需路由到同一容器 |
Nginx 反向代理最小配置片段:
```nginx
location /v1/api/chat_callback {
proxy_pass http://backend:3001;
proxy_buffering off;
proxy_cache off;
proxy_set_header X-Forwarded-For $remote_addr;
}
location / {
proxy_pass http://backend:3001;
proxy_set_header X-Forwarded-For $remote_addr;
}
```
---
## .gitignore 建议
确保以下文件不进入版本库:
```gitignore
.env
.env.staging.local
.env.production
*.local
```
`.env.staging`(仅含占位符的模板)可以提交,便于团队成员了解需要配置哪些变量。
---
## 快速参考
```bash
# 开发
uv run uvicorn server:app --reload
# 测试环境Docker
docker compose -f docker-compose.yml -f docker-compose.staging.yml up --build
# 生产镜像构建
docker build -t aigc-backend:$(git rev-parse --short HEAD) .
# 查看健康状态
curl http://localhost:3001/health
# 查看容器日志
docker compose logs -f backend
```