# 部署指南 本文档说明如何用 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。 - 开启日志采集和容器监控。