Files
Cloud-Tour-to-Libo/docs/DEPLOYMENT.md
T
xuelong 3dd5731751 feat: streamline platform and secure data access
- move the relational data center to MySQL and a standalone workbench\n- add Interface Center API credentials, policies, logs, and DBeaver SSH guidance\n- harden authentication and deployment while retiring unused management surfaces
2026-08-25 02:06:28 -07:00

332 lines
11 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.
# 部署指南
本文档说明如何用 Docker 启动、重置、配置和排查旅行知识图谱管理系统。
## 环境要求
- Docker Desktop 或 Docker Engine
- Docker Compose v2
- 至少 4 GB 可用内存
- 开发环境至少 10 GB、生产环境至少 50 GB 可用磁盘空间,并单独规划异地备份容量
## 本地开发启动
```bash
docker compose up -d --build
```
启动后访问:
```text
http://localhost:8102/admin
```
以下默认账号只允许本地开发使用:
```text
admin@example.com / change-me
```
生产环境必须先完成后文中的密钥、域名、HTTPS 和防火墙配置,再使用服务器覆盖文件启动:
```bash
docker compose -f docker-compose.yml -f docker-compose.server.yml up -d --build
```
## 首次启动会发生什么
1. 构建 API 镜像,并打包 React 管理后台。
2. 创建 PostgreSQL 数据卷。
3. PostgreSQL 初始化脚本恢复 `snapshots/postgres/kg_admin_new2.dump`。
4. `falkordb-seed` 把 `snapshots/falkordb/dump.rdb` 写入 FalkorDB 数据卷。
5. FastAPI 服务等待 PostgreSQL 和 FalkorDB 健康后启动。
## 常用命令
查看服务状态:
```bash
docker compose ps
```
查看 API 日志:
```bash
docker compose logs -f api
```
停止服务:
```bash
docker compose down
```
停止并删除数据卷,下一次启动将重新恢复快照:
```bash
docker compose down -v
docker compose up -d --build
```
## 无 sudo 服务器的 rootless Docker 启动
如果服务器账号不能使用 `sudo`,并且 `loginctl show-user <用户> -p Linger` 显示 `Linger=no`,用户级 `docker.service` 可能会在 SSH 退出后停止。此时可以使用项目脚本把 rootless Docker 的 socket 固定到用户目录:
```bash
cd /home/dockerop/travel-knowledge-graph
./scripts/server_rootless_docker.sh start
./scripts/server_rootless_docker.sh up
./scripts/server_rootless_docker.sh ps
./scripts/server_rootless_docker.sh health
```
本项目在 `8.163.40.99` 的当前部署使用:
```bash
DOCKER_HOST=unix:///home/dockerop/.docker/run/docker.sock
```
如果服务器重启,重新执行:
```bash
cd /home/dockerop/travel-knowledge-graph
./scripts/server_rootless_docker.sh up
```
更推荐的长期方式是让服务器管理员执行:
```bash
sudo loginctl enable-linger dockerop
```
这样 rootless Docker 可以由 systemd 用户服务长期托管。
## 生产安全入口
服务器覆盖配置默认令 API 只监听 `127.0.0.1:8102`。公网只能通过 Nginx 的
HTTPS 443 端口访问,不再直接开放 8102。可复制
`deploy/nginx/travel-kg.conf.example`,替换域名和证书路径后启用。
安全组入站规则建议仅保留:
- `443/tcp`:所有合法业务来源;
- `22/tcp`:仅运维固定 IP 或 VPN 网段;
- `80/tcp`:仅用于跳转 HTTPS 或证书签发。
严禁向公网开放 `8102`、`3307`、`5433`、`6380` 和 `3002`。
## 端口配置
可以在启动时覆盖端口:
```bash
API_PORT=18102 \
POSTGRES_PORT=15433 \
FALKORDB_PORT=16380 \
FALKORDB_BROWSER_PORT=13002 \
docker compose up -d --build
```
默认端口:
| 变量 | 默认值 | 说明 |
| --- | --- | --- |
| `API_HOST_BIND` | `0.0.0.0` | 本地 Compose 的 API/后台监听地址 |
| `API_BIND_HOST` | 服务器覆盖默认 `127.0.0.1` | 生产 Uvicorn 监听地址,只允许 Nginx 转发 |
| `API_PORT` | `8102` | FastAPI 与管理后台 |
| `POSTGRES_HOST_BIND` | `127.0.0.1` | PostgreSQL 只绑定服务器本机 |
| `POSTGRES_PORT` | `5433` | PostgreSQL 映射端口 |
| `MYSQL_HOST_BIND` | `127.0.0.1` | MySQL 只绑定服务器本机,DBeaver 经 SSH 隧道接入 |
| `MYSQL_PORT` | `3307` | MySQL 服务器本机映射端口,不向公网开放 |
| `FALKORDB_HOST_BIND` | `127.0.0.1` | FalkorDB Redis 协议只绑定服务器本机 |
| `FALKORDB_PORT` | `6380` | FalkorDB Redis 协议端口 |
| `FALKORDB_BROWSER_HOST_BIND` | `127.0.0.1` | FalkorDB Browser 只绑定服务器本机 |
| `FALKORDB_BROWSER_PORT` | `3002` | FalkorDB Browser |
## 环境变量
基础 Docker Compose 提供开发默认值;服务器覆盖配置会对关键变量使用必填校验,
任何占位密码、弱签名密钥、公开 MySQL 绑定、通配 CORS 或不可信 Host 都会令
应用拒绝启动。
服务器首次部署建议复制模板后修改:
```bash
cp .env.example .env
```
至少修改:
```env
AUTH_SECRET=换成32位以上随机字符串
AUTH_DEFAULT_PASSWORD=换成12位以上后台管理员密码
INTERFACE_API_SECRET=与AUTH_SECRET不同的32位以上随机字符串
INGEST_API_KEYS=至少24位的外部系统接口Key
CORS_ALLOWED_ORIGINS=https://你的后台域名
TRUSTED_HOSTS=你的后台域名
LLM_API_BASE=你的OpenAI兼容模型地址
LLM_API_KEY=你的模型Key
```
新系统不再提供后台 Agent 设置页面。LLM 与外部接口 Key 统一通过 `.env`、Compose 环境变量或部署平台的密钥配置维护。
| 变量 | 说明 |
| --- | --- |
| `POSTGRES_USER`、`POSTGRES_PASSWORD`、`POSTGRES_DB` | PostgreSQL 容器账号、密码、库名 |
| `DATABASE_URL` | 后端连接 PostgreSQL 的 URL |
| `DB_SCHEMA` | 默认 `kg_admin_new2` |
| `DB_MIGRATIONS_ENABLED` | 快照部署默认 `false` |
| `DATA_MYSQL_SSH_HOST`、`DATA_MYSQL_SSH_PORT` | DBeaver SSH 标签页使用的服务器地址和 SSH 端口 |
| `DATA_MYSQL_ADMIN_HOST`、`DATA_MYSQL_ADMIN_PORT` | DBeaver Main 标签页使用的隧道远端 MySQL 地址,默认 `127.0.0.1:3307` |
| `DATA_MYSQL_AUDIT_ENABLED` | 只有数据库审计真实启用后才设置为 `true` |
| `DATA_SQL_CONSOLE_WRITE_ENABLED` | 默认 `false`,生产 SQL 控制台保持只读 |
| `DATA_BACKUP_ENABLED` | 自动备份任务真实部署后才设置为 `true` |
| `DATA_BACKUP_PASSPHRASE_FILE` | 仓库外的备份加密口令文件,权限必须为 600 |
| `FALKORDB_HOST` | Docker 内默认 `falkordb` |
| `FALKORDB_GRAPH` | 默认业务图 `guiyang_new2` |
| `AUTH_SECRET` | JWT 签名密钥,生产必须替换 |
| `INTERFACE_API_SECRET` | 接口密钥散列专用密钥,不得与 JWT 密钥复用 |
| `AUTH_DEFAULT_USERNAME` | 默认管理员用户名 |
| `AUTH_DEFAULT_PASSWORD` | 默认管理员密码 |
| `LLM_API_BASE` | OpenAI 兼容模型服务地址,可选 |
| `LLM_API_KEY` | LLM 密钥,可选 |
| `LLM_EXTRACTION_ENABLED` | 是否启用 LLM 抽取 |
| `AMAP_WEB_KEY`、`AMAP_JS_KEY` | 高德地图密钥,可选 |
| `GAODE_CRAWLER_PATH` | 外部高德采集脚本路径,可选 |
| `TRAVEL_AGENCY_SOURCE_ROOT` | 旅行社原始资料目录,仅运行采集/构图脚本时需要 |
| `TRAVEL_DELIVERY_ROOT` | POI 交付 CSV 目录,仅运行采集/增强脚本时需要 |
| `TRAVEL_KG_EXPORT_ROOT` | 采集/构图脚本导出目录 |
## 百姓惠智能客服接口
给外部系统对接时,只开放这个接口即可:
```text
POST https://你的域名/v1/openapi/knowledge-qa/query
```
`/v1/admin/travel/customer-service-query` 会继续保留为兼容旧调用,新接入的第三方系统建议统一使用 `/v1/openapi/knowledge-qa/query`。
生产服务器不应放行 TCP `8102`。服务器本机可用
`curl http://127.0.0.1:8102/v1/admin/health` 检查应用,外部统一访问
`https://你的域名/`。不要把 `3307`、`5433`、`6380`、`3002` 暴露到公网。
生产环境必须通过环境变量 `INGEST_API_KEYS` 配置至少一个接口 Key;未配置时,对外问答接口会返回 `503`,避免无鉴权开放。
接口 Key 是给第三方系统调用本接口用的访问凭证;问答环节 LLM 的 API Key 是本系统调用大模型用的凭证,两者不要混用。
请求示例:
```bash
curl https://你的域名/v1/openapi/knowledge-qa/query \
-H 'Content-Type: application/json' \
-H 'X-KG-API-Key: 你的INGEST_API_KEYS之一' \
-d '{
"request_id": "crm-msg-20260610-0001",
"question": "黄小西三日游多少钱?",
"graph_name": "baixinghui_travel_agency",
"session_id": "demo-001",
"channel": "online_service",
"use_llm": true,
"llm_fusion": true
}'
```
## MySQL 加密备份
先在代码仓库之外创建口令文件:
```bash
sudo install -d -m 700 /etc/travel-kg/secrets
openssl rand -base64 48 | sudo tee /etc/travel-kg/secrets/mysql-backup-passphrase >/dev/null
sudo chmod 600 /etc/travel-kg/secrets/mysql-backup-passphrase
```
执行备份和校验:
```bash
export DATA_BACKUP_PASSPHRASE_FILE=/etc/travel-kg/secrets/mysql-backup-passphrase
./scripts/backup_mysql_encrypted.sh
./scripts/verify_mysql_backup.sh ./backups/mysql/mysql-all-时间.sql.gz.enc
```
备份采用 `mysqldump --single-transaction`、gzip 和 AES-256/PBKDF2,并生成
SHA-256 校验文件。`.enc`、`.sha256`、`.json` 三个文件必须同步到独立账号的
异地对象存储。校验脚本不等于恢复演练;至少每月在隔离 MySQL 实例执行一次
完整恢复,确认账号、表结构和业务数据均可恢复。
默认问答链路需要配置问答环节 LLM;可在后台 `外部图谱问答 API -> 问答环节 LLM 模型` 单独配置,也可以继承全局 LLM。
主要返回字段:
| 字段 | 说明 |
| --- | --- |
| `request_id` | 外部请求 ID,原样回传或由服务端生成 |
| `trace_id` | 服务端链路追踪 ID |
| `answer` | 给外部系统展示的完整回答 |
| `customer_reply` | 可以直接发给客户的话术 |
| `follow_up_questions` | 建议追问 |
| `risk_notes` | 需要二次核实或不可直接承诺的事项 |
| `knowledge.plans` | 图谱命中的线路/方案 |
| `knowledge.evidence` | 图谱证据 |
## 健康检查
API:
```bash
curl http://localhost:8102/v1/admin/health
```
PostgreSQL:
```bash
docker compose exec postgres pg_isready -U admin -d kg_admin
```
FalkorDB:
```bash
docker compose exec falkordb redis-cli -p 6379 PING
```
## 常见问题
### 管理后台 404
确认镜像已重新构建:
```bash
docker compose up -d --build api
```
前端静态资源由 FastAPI 挂载在 `/admin`,直接访问根路径不会进入后台。
### 数据没有恢复
PostgreSQL 初始化脚本只在数据卷首次创建时运行。如果已经创建过数据卷,需要先删除卷:
```bash
docker compose down -v
docker compose up -d --build
```
### 端口被占用
使用端口变量覆盖默认端口,例如:
```bash
API_PORT=18102 docker compose up -d
```
### 登录失败
初始化脚本会把 `admin@example.com` 的演示密码设置为 `change-me`。如果仍失败,先确认 PostgreSQL 已重新恢复快照,再查看 API 日志。
## 生产加固建议
- 修改 `AUTH_SECRET`、数据库密码和默认管理员密码。
- 不要把真实 `.env`、LLM key、高德 key 提交到仓库。
- 用反向代理提供 HTTPS。
- 给 PostgreSQL 和 FalkorDB 配置持久化备份。
- MySQL、PostgreSQL 和 FalkorDB 全部只绑定服务器本机;DBeaver 经 SSH 私钥隧道接入,公网只暴露 HTTPS 和受控 SSH。
- 开启日志采集和容器监控。