本文件讲通用做法:任何一台机器 + 一个反向代理/隧道都能照此部署。
| 文件 | 干什么 | 在基线里吗 |
|---|---|---|
dev.sh |
起/停三个进程(start / restart / stop;只有这三个子命令) |
✅ |
visual.sh |
视觉查询服务单独起停(start / stop / restart / status / logs);dev.sh 委托它 |
✅ |
ci.sh |
不需要外部服务与模型的门禁(CI 与本地同一份命令) | ✅ |
monitor.py |
十四项巡检(队列、索引对账、磁盘、卡住的文档…);“跳过”不算健康 | ✅ |
backup.sh / restore.sh |
备份 PG + blobs(Qdrant 不备份,靠重建);恢复到临时库并逐表对账 | 手工 |
seed_photos.py |
造持久照片库(幂等);账号与口令从 .env 读 |
手工 |
measure_visual_leg.py |
量视觉腿的成本与收益(含并发那一维) | 手工 |
verify_*.py |
端到端手工验证(上传/检索/视觉降级…) | 手工(不在基线) |
docker-compose.yml |
只起基础设施:postgres(pgvector) + qdrant |
手工 |
# 1) 基础设施(只有这两个容器;应用不进容器)
docker compose -f deploy/docker-compose.yml up -d
# 2) 应用三个进程:API(8010) · worker · 视觉查询服务(8020)
bash deploy/dev.sh start
bash deploy/dev.sh restart # 改了后端代码之后必须用这个
# 2b) 视觉服务也可单独管理(脚本化部署,不用 systemd)
bash deploy/visual.sh start|stop|restart|status|logs
# 3) 前端构建产物由 API 托管(dev.sh 不会替你构建)
cd web && npm install && npm run build
| 端口 | 谁 |
|---|---|
8010 |
API(同时托管前端构建产物与 /mcp、/a2a/tasks) |
8020 |
视觉查询服务:只做编码,常驻 colSmol(约 2.65GB) |
5173 |
只有本地开发才需要(cd web && npm run dev) |
5432 / 6333 |
Postgres(pgvector) / Qdrant |
⚠️ 三个进程必须用 dev.sh / visual.sh 管:kill -- -PID 杀不干净 uv run 派生的子进程,
残留的旧 worker 会继续用旧代码领任务,症状是”改了没生效”。
视觉服务的生命周期只有一份实现(visual.sh),dev.sh 委托它 —— 单独起停与整套编排不会漂移。
bash deploy/backup.sh # 备份 + 自检(生成 manifest)
bash deploy/restore.sh --scratch data/backups/<时间戳> # 恢复到临时库 → 逐表对账 → 逐个 sha256
POST /admin/reindex),
所以备份只要保证 PG + blobs 完整。backup.sh 看它”成功”证明不了能恢复。uv run python deploy/monitor.py # 十四项;退出码 1 = 有项不健康
想让全量重建时旧索引仍可读(零停机),开别名模式:
uv run python deploy/bootstrap_index_aliases.py --yes # 一次性:真实集合 → 物理集合 + 别名
# 在 .env 设 QDRANT_ALIASES=true 并重启 API / worker
# 之后重建:POST /api/v1/admin/reindex?swap=true(需超管)
GET /collections,所以巡检里列的是物理集合名 —— 正常。对外只需要一个端口:把 8010 交给反向代理或隧道即可(API 已托管前端产物;
/mcp 与 /a2a/tasks 在根路径,不在 /api/v1 下)。
| 该做 | 为什么 |
|---|---|
| 边缘再加一层访问控制(隧道侧的 Access / 反代 basic auth / 只允许局域网) | 应用内的鉴权只有 API Key 一道,它保护的是数据,不保护登录页与限流 |
ALLOW_REGISTER=false |
否则陌生人可以自助建号(.env 里默认按部署场景决定) |
| 登录失败限流保持开启 | 这是唯一不需要凭证就能到达的数据入口 |
不要暴露 8020(视觉服务) |
它没有鉴权,只绑 127.0.0.1;指到 0.0.0.0 等于对外开放一个模型服务 |
不要暴露 5432 / 6333 |
数据库与向量库没有应用层租户概念 |
定期跑 monitor.py + 每月做一次恢复演练 |
见上 |
⚠️ 视觉服务是可选的:VISUAL_SERVICE_URL=(留空)就关掉视觉腿,检索照常返回
(那一条腿如实标 skipped)。小内存机器上这是推荐的默认。