Files
yunke/docs/DEPLOY.md
T

182 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.
# 云客数据镜像 — 服务器部署指南
> 2026-08-21|适用于 Linux 服务器 + Docker Compose 五服务部署
## 架构
```
┌─────────────────────────────────────────────────┐
│ Docker Compose │
│ ┌────────┐ ┌────────┐ ┌────────────────────┐ │
│ │ MySQL 8│ │ Redis 7│ │ backend (FastAPI) │ │
│ │ :3306 │ │ :6379 │ │ :8000 │ │
│ └────┬───┘ └────┬───┘ └─────────▲──────────┘ │
│ │ │ │ /api │
│ ┌────▼───────────▼───┐ ┌────────┴──────────┐ │
│ │ scheduler │ │ frontend (nginx) │ │
│ │ APScheduler │ │ :5173 → :80 │ │
│ │ + Playwright │ └───────────────────┘ │
│ │ + Chromium │ │
│ └────────────────────┘ │
└─────────────────────────────────────────────────┘
```
- **scheduler**:每晚 02:00 全量 + 每 4h 消息增量 + 每周日 05:00 全量对齐(全部浏览器 fetch 零风控)→ 需要 Playwright + Chromium(镜像已内置)
- **restart: unless-stopped**:容器崩溃自动重启(服务器上的守护方案,无需本地计划任务)
## 前置要求
- Linux 服务器(2C4G 起步,磁盘 ≥ 20GB:MySQL 数据 + 媒体文件 2.5GB+)
- Docker 24+ 与 Docker Compose v2
- 一个有效的云客会话 cookie(从浏览器登录云客后复制)
## 部署步骤
### 1. 上传代码
```bash
git clone <你的仓库地址> yunke
cd yunke
```
### 2. 配置 .env
```bash
cp yunke-server/.env.example .env # 或手动创建
```
必须设置的项:
```ini
# 云客会话(从浏览器 F12 → Network → 任意请求的 Cookie 头复制)
YK_USERID=<32位userId>
YK_COMPANY=<公司码>
YK_COOKIE=user=xxx; userToken=yyy
# MySQL(docker-compose 自动创建库和用户)
MYSQL_ROOT_PASSWORD=<强密码>
MYSQL_PASSWORD=<强密码>
# 查看后台的访问令牌(留空=无鉴权,仅限内网)
API_TOKEN=<随机长字符串>
```
### 3. 启动
```bash
docker compose --env-file .env up -d --build
```
首次构建约 5-10 分钟(含 Chromium 下载 ~150MB)。启动后:
```bash
docker compose ps # 五服务全部 Up(healthy)
docker compose logs -f scheduler # 看调度器日志
```
### 4. 数据库迁移(alembic schema)
后端启动**不会**自动建表,schema 由 alembic 迁移链管理(镜像已打包
`alembic.ini` + `migrations/`,`DB_URL` 由 compose 注入)。
**新库首次部署**(空 MySQL 直接建全量表):
```bash
docker compose exec backend alembic upgrade head
```
**旧库升级**(2026-08-22 `migrate_sqlite_to_mysql.py` 搬迁产物,没有
alembic_version 表)——2026-08-25 实战踩通的完整路径,原样记录:
```bash
# 1) 前置校验:chat_group 无 NULL owner_account_id(复合 PK 迁移要求 NOT NULL,
# 非 0 则是必须人工核对的数据问题,不要带病升级)
docker compose exec mysql mysql -uyunke -p<密码> yunke \
-e "SELECT COUNT(*) FROM chat_group WHERE owner_account_id IS NULL"
# 2) stamp 到搬迁脚本对应的链上位置,再升级到 head
docker compose exec backend alembic stamp d8eee96cd017
docker compose exec backend alembic upgrade head
```
stamp 版本号不是拍脑袋定的:`d8eee96cd017` 是与 2026-08-22
`migrate_sqlite_to_mysql`(按当时模型 `create_all` 建表)产物 schema
一致的链上位置——stamp 它即声明「到此为止已应用」,其后迁移(chat_group
复合 PK、群主列、类型修正等)逐一正常补上。其它日期建的旧库须自行核对
表结构选 stamp 点,不要照抄这个版本号。
**每次拉新代码后**:
```bash
docker compose exec backend alembic upgrade head
```
> ⚠️ 类型变更类迁移(如 fe63c6789e94)在 MySQL 上为 COPY 算法、会锁
> `message` 等大表写入——避开抓取窗口(每 4h 增量、02:00 全量)执行。
涉及存量数据回填的更新另跑回填脚本(幂等,重跑 0 改动;脚本默认连
`./smoke.db`,服务器上须显式传 DB_URL——容器 env 已带,直接透传):
```bash
docker compose exec backend python -c "import asyncio,os; from scripts.backfill_chat_group_fields import main; asyncio.run(main(os.environ['DB_URL']))"
docker compose exec backend python -c "import asyncio,os; from scripts.backfill_msg_types import main; asyncio.run(main(os.environ['DB_URL']))"
```
### 5. 验证
```bash
curl http://localhost:8000/api/health # {"status":"ok"}
curl http://localhost:5173/ # 前端页面
```
### 6. 数据迁移(把本地 SQLite 数据搬到服务器 MySQL)
**方式 A:重抓(推荐,数据最新)**
服务器上手动跑一轮全量:
```bash
docker compose exec scheduler bash
DB_URL="mysql+asyncmy://yunke:<密码>@mysql:3306/yunke" \
bash scripts/full_sync_all.sh
```
耗时 6-12 小时(消息全量翻页),跑完后调度器自动接管日常增量。
**方式 B:SQLite → MySQL 数据搬迁**
把本地 smoke.db 和 media/ 目录传到服务器,用 Python 脚本逐表导:
(如有需要我可以写迁移脚本,~100 行)
### 7. 媒体文件
媒体存在 Docker volume `media_data` 里。本地已有 2.5GB 媒体的话:
```bash
# 本地打包
tar czf media.tar.gz -C yunke-server media/
# 传到服务器后灌入 volume
docker run --rm -v yunke_media_data:/target -v $(pwd):/src alpine \
sh -c "cd /target && tar xzf /src/media.tar.gz --strip-components=1"
```
## 日常运维
| 操作 | 命令 |
|---|---|
| 看调度日志 | `docker compose logs -f scheduler` |
| 手动触发全量 | `docker compose exec scheduler bash scripts/full_sync_all.sh` |
| 换 cookie | 改 `.env` 的 `YK_COOKIE` → `docker compose restart scheduler backend` |
| 备份 MySQL | `docker compose exec mysql mysqldump -uroot -p<密码> yunke > backup.sql` |
| 备份媒体 | `docker run --rm -v yunke_media_data:/data -v $(pwd):/out alpine tar czf /out/media.tgz -C /data .` |
| 升级版本 | `git pull && docker compose up -d --build && docker compose exec backend alembic upgrade head`(回填见「数据库迁移」) |
## 已知注意事项
1. **cookie 过期**:云客会话定期失效,过期后日志出现 `⚠️ cookie 可能已过期` 提示 → 从浏览器重新复制 `YK_COOKIE` 并 restart
2. **首次消息全量很慢**(6-12h),之后增量每轮 15-30 分钟
3. **FTS 搜索**:MySQL 上自动回退 LIKE(暂无全文索引);如搜索量大可在 MySQL 建 FULLTEXT 索引
4. **时区**:容器默认 UTC;调度按容器时区触发(FULL_SYNC_HOUR=2 即 UTC 02:00)。要北京时间可在 compose 加 `TZ: Asia/Shanghai`
5. **服务器需能访问 crm2.yunkecn.com 和 *.oss.yunkecn.com**(抓取 + 媒体下载)