docs: 线上部署实录文档(环境/链路/反代配置/发版流程/踩坑手册/运维命令)
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,200 @@
|
||||
# 线上部署文档(生产环境实录)
|
||||
|
||||
> 更新:2026-09-30 · 对应线上版本 `5d83dd9`
|
||||
> 本文记录**实际部署状态**(不是理想方案),排查问题和重新部署都以此为准。
|
||||
|
||||
## 1. 线上环境总览
|
||||
|
||||
| 项 | 值 |
|
||||
|---|---|
|
||||
| 目标服务器 | 阿里云 ECS(境外)`47.254.176.10`,Debian 13,Docker 29.4.0,1Panel 面板 |
|
||||
| 跳板机 | 国内阿里云 `8.152.213.143`(境外机直连不通,必须经跳板) |
|
||||
| 线上域名 | `https://chat2.agent.hnxinyouhe.com`(1Panel 建站,HTTPS 证书已绑定) |
|
||||
| 应用容器 | `hs-ai-kefu`(端口 `8017:8000`,内存限额 512M) |
|
||||
| 代码位置 | `/opt/1panel/www/sites/chat2.agent.hnxinyouhe.com/index`(git clone 自公司 git) |
|
||||
| git 仓库 | `http://219.157.255.213:25311/xinyouhe/ai-kefu-jc.git` |
|
||||
|
||||
**同服务器共存的其它项目(部署/排障时绝对不要碰)**:
|
||||
汽车客服 `cc-ai-kefu`(`chat.agent.hnxinyouhe.com`,端口 8016)、tracker 系列、
|
||||
photo-live 系列、php7433 等。本项目与它们仅共享 Docker 守护进程,容器/端口/目录/数据完全隔离。
|
||||
|
||||
## 2. SSH 连接方式(专属密钥 + 跳板链路)
|
||||
|
||||
本机 `~/.ssh/config` 已配好两个别名(密钥为本项目专属 `~/.ssh/ai_kefu_jc_deploy`,
|
||||
吊销 = 删服务器 `~/.ssh/authorized_keys` 中带 `ai-kefu-jc-deploy` 注释的行):
|
||||
|
||||
```
|
||||
Host ai-kefu-jc-bastion # 跳板(国内)
|
||||
HostName 8.152.213.143 / User root / Port 22
|
||||
|
||||
Host ai-kefu-jc-prod # 目标(境外,经跳板)
|
||||
HostName 47.254.176.10 / User root / Port 22
|
||||
ProxyJump ai-kefu-jc-bastion
|
||||
```
|
||||
|
||||
```bash
|
||||
ssh ai-kefu-jc-prod 'echo ok' # 一键直达到目标服务器
|
||||
```
|
||||
|
||||
## 3. 服务器上的实际布局
|
||||
|
||||
```
|
||||
/opt/1panel/www/sites/chat2.agent.hnxinyouhe.com/
|
||||
├── index/ ← 项目根(git 仓库,即部署目录)
|
||||
│ ├── app/ static/ tests/ ...
|
||||
│ ├── docker-compose.yml ← 注意:服务器上有本地改动(mem_limit 512m,未提交)
|
||||
│ ├── deploy.sh ← 同上(本地改动)
|
||||
│ ├── data/hesupipe_ai_kefu.db ← 生产 SQLite(容器卷挂载,gitignore)
|
||||
│ └── .env ← 生产配置(gitignore,权限600)
|
||||
├── log/ ← 站点访问日志
|
||||
├── ssl/ ← HTTPS 证书(1Panel 管理)
|
||||
└── proxy/ ← 反代配置(1Panel 站点的 include 加载)
|
||||
├── root.conf ← HTTP 全站反代 → 127.0.0.1:8017
|
||||
└── ws.conf ← WebSocket 专用路由(与汽车客服同款)
|
||||
```
|
||||
|
||||
1Panel 主配置:`/opt/1panel/www/conf.d/chat2.agent.hnxinyouhe.com.conf`
|
||||
(其中第 19 行 `include /www/sites/chat2.agent.hnxinyouhe.com/proxy/*.conf;`
|
||||
是部署时手工补的 —— **1Panel 建站默认不带 include,面板配的反代不会生效**,
|
||||
备份在同目录 `*.conf.bak.20260930`)。
|
||||
|
||||
### 反代实际生效配置(排查时对照)
|
||||
|
||||
`proxy/root.conf`(HTTP):
|
||||
```nginx
|
||||
location ^~ / {
|
||||
proxy_pass http://127.0.0.1:8017;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 300s;
|
||||
}
|
||||
```
|
||||
|
||||
`proxy/ws.conf`(WebSocket 专用,`/ws/` 前缀优先命中):
|
||||
```nginx
|
||||
location /ws/ {
|
||||
proxy_pass http://127.0.0.1:8017;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 3600s;
|
||||
proxy_send_timeout 3600s;
|
||||
}
|
||||
```
|
||||
|
||||
> ⚠️ 反代改动后要重载:`docker exec $(docker ps --filter name=openresty -q | head -1) nginx -t && nginx -s reload`
|
||||
> (先 `-t` 语法检查再 reload;reload 是平滑的,不影响其他站点)
|
||||
|
||||
## 4. 生产 .env(结构,值脱敏)
|
||||
|
||||
```ini
|
||||
AI_PROVIDER=glm
|
||||
ZHIPU_API_KEY=<与汽车项目同一个>
|
||||
AI_MODEL=glm-4-flash
|
||||
ZHIPU_BASE_URL=<同汽车项目>
|
||||
|
||||
DATABASE_URL=sqlite+aiosqlite:///./data/hesupipe_ai_kefu.db
|
||||
|
||||
SMTP_HOST/PORT/USER/PASS=<真实发件账号,同汽车项目>
|
||||
NOTIFY_EMAIL=hesu@hesuu.com # 询盘通知收件箱
|
||||
|
||||
PUSH_ENABLED=false # 暂不推送 UniService(需求方决定)
|
||||
PUSH_API_URL=https://uniservice.server.hnxinyouhe.com/open/v1/inquiry/push
|
||||
PUSH_API_KEY=<已备好,开启时用>
|
||||
PUSH_EXTERNAL_KEY_PREFIX=ai-kefu-jc # 与汽车项目线索键隔离,勿改!
|
||||
|
||||
APP_HOST=0.0.0.0
|
||||
APP_PORT=8017
|
||||
APP_DEBUG=false
|
||||
```
|
||||
|
||||
凭据来源:部署时从汽车项目服务器上的 `.env`(`chat.agent.hnxinyouhe.com/index/.env`)
|
||||
提取同类键,**只读未动**。
|
||||
|
||||
## 5. 部署 / 更新流程(日常发版照此执行)
|
||||
|
||||
```bash
|
||||
# 0. 本地:测试全绿才发版
|
||||
python -m pytest -q # 231 项
|
||||
|
||||
# 1. 本地:推送
|
||||
git push origin master
|
||||
|
||||
# 2. 服务器:更新并重建(一条命令)
|
||||
ssh ai-kefu-jc-prod '
|
||||
cd /opt/1panel/www/sites/chat2.agent.hnxinyouhe.com/index
|
||||
git stash && git pull && git stash pop # stash 保住服务器本地改动(mem_limit等)
|
||||
docker compose build && docker compose up -d
|
||||
sleep 3 && curl -s http://127.0.0.1:8017/health
|
||||
'
|
||||
```
|
||||
|
||||
说明:
|
||||
- 静态文件(widget.js 等)**打进镜像**,改前端必须 `build`(仅 `up -d` 不够)
|
||||
- `.env` 和 `data/` 不在 git 里,更新不受影响
|
||||
- 回滚:`git checkout <上一版本> && docker compose build && docker compose up -d`
|
||||
|
||||
## 6. 验证清单(发版后必跑)
|
||||
|
||||
```bash
|
||||
# ① 健康
|
||||
curl -s https://chat2.agent.hnxinyouhe.com/health # {"status":"ok"}
|
||||
# ② 页面
|
||||
curl -s https://chat2.agent.hnxinyouhe.com/ | grep -o "<title>.*</title>"
|
||||
# ③ WebSocket(期待 HTTP/1.1 101)
|
||||
curl -s -i --http1.1 -H "Connection: Upgrade" -H "Upgrade: websocket" \
|
||||
-H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" -H "Sec-WebSocket-Version: 13" \
|
||||
https://chat2.agent.hnxinyouhe.com/ws/chat | head -1
|
||||
# ④ 静态与缓存头
|
||||
curl -sI https://chat2.agent.hnxinyouhe.com/static/widget.js | grep -i "cache\|HTTP"
|
||||
```
|
||||
|
||||
功能级验证(改前端/挂件后):打开
|
||||
`https://chat2.agent.hnxinyouhe.com/static/widget-test.html`,
|
||||
用 Playwright 或肉眼核对:邀请卡 5 秒弹出位置、面板四个方位(data-position)、
|
||||
头像加载、主题色断言面板 9/9 绿。
|
||||
|
||||
## 7. 本次上线踩坑实录(排查手册)
|
||||
|
||||
| 现象 | 根因 | 解法(已内置,重蹈覆辙时对照) |
|
||||
|---|---|---|
|
||||
| WS 握手 426(HTTP 正常) | 1Panel 面板生成的反代里 `Upgrade/Connection` 头**重复定义两套**,uvicorn 严格解析直接拒绝 | 拆分 ws.conf 单套路(§3),`nginx -T` dump 最终配置 + 假后端 dump 收到的头可快速定位 |
|
||||
| 改了 widget.js 线上"没生效" | 响应无 Cache-Control,浏览器启发式缓存旧脚本 | 已加中间件 `/static/* → Cache-Control: no-cache`(ec2d17b);用户端 Ctrl+F5 一次即愈 |
|
||||
| bottom-left 弹出元素溢出屏幕(面板 x=-183) | 弹出层(chat-panel / invite-container)CSS 硬编码 `right:0` 只适配右下角 | 已随 `pos-<position>` 类联动(5d83dd9),静态测试锁死;**新增弹出元素时必须同时加联动规则** |
|
||||
| 1Panel 配了反代不生效 | 面板建站的主 conf 默认不含 `include proxy/*.conf` | 手工补 include 行(§3),备份后 reload |
|
||||
| deploy 时 `git pull` 报本地改动冲突 | 服务器 compose/deploy.sh 有本地改动(mem_limit) | `git stash && git pull && git stash pop`(已写入 §5 流程) |
|
||||
|
||||
## 8. 常见运维操作
|
||||
|
||||
```bash
|
||||
# 看应用日志(最近100行)
|
||||
ssh ai-kefu-jc-prod 'docker logs hs-ai-kefu --tail 100'
|
||||
|
||||
# 重启应用(不动其他容器)
|
||||
ssh ai-kefu-jc-prod 'cd /opt/1panel/www/sites/chat2.agent.hnxinyouhe.com/index && docker compose up -d --force-recreate'
|
||||
|
||||
# 容器状态/内存
|
||||
ssh ai-kefu-jc-prod 'docker stats hs-ai-kefu --no-stream'
|
||||
|
||||
# 破防率观测(上线第一周必做,见 CLAUDE.md 观察期)
|
||||
ssh ai-kefu-jc-prod 'docker exec hs-ai-kefu python scripts/breach_rate.py'
|
||||
|
||||
# 管理后台
|
||||
https://chat2.agent.hnxinyouhe.com/admin # 密码在生产 .env 同汽车项目口径
|
||||
```
|
||||
|
||||
## 9. 待办与提醒
|
||||
|
||||
- [ ] 官网嵌入:hesupipe.com 按 `docs/embed-guide.md`(script src 用
|
||||
`https://chat2.agent.hnxinyouhe.com/static/widget.js`,位置/配色/邮箱可配)
|
||||
- [ ] 邮件通道冒烟:跑一轮测试留资,确认 hesu@hesuu.com 能收到询盘邮件
|
||||
(单邮件通道,SMTP 失败不自动补发,上线头几天盯收件)
|
||||
- [ ] 开启 UniService 推送(届时只改 `.env` 的 `PUSH_ENABLED=true` 并重启容器)
|
||||
- [ ] 上线第一周:跑 breach_rate 观测漏放/误杀(已知 4 项残差见 docs/test-checklist.md)
|
||||
- [ ] 服务器本地改动(compose mem_limit / deploy.sh)择机整理进 git,消除 stash 依赖
|
||||
Reference in New Issue
Block a user