docs(dobotai): add container deployment guide

This commit is contained in:
姚章浩
2026-09-10 22:25:19 +08:00
parent 8027635330
commit e584b17929
+259 -20
View File
@@ -1,29 +1,153 @@
# DobotAI 容器化运行(测试环境)
# DobotAI DingTalk 容器部署手册
容器和Compose服务固定名为 `dobotai-dingtalk`。容器使用宿主网络,以兼容测试环境已有的 `127.0.0.1` PostgreSQL、WeKnora和健康检查地址;它不暴露新端口,不更改数据库容器或WeKnora容器。
> 适用范围:DobotAI 测试环境的容器化运行。容器和 Compose 服务名固定为 `dobotai-dingtalk`。
> 本文不授权生产部署;生产必须使用已验收的同一镜像、独立备份和独立变更审批。
## 日常操作
## 1. 定位
完成一次安装后,日常仅需要两条命令:
DobotAI 是钉钉渠道的对话编排与交付层,不是知识库或文档解析平台。
它负责:
- 接收钉钉 Stream 消息、富文本和图片;
- 将请求路由到 WeKnora Agent,并维护渠道会话;
- 通过钉钉 AI 卡片或 Markdown 流式交付回答;
- 处理 `/think`、`/setting` 等渠道命令;
- 保存 Turn、会话映射、覆盖判定、Support Case、反馈和审计数据;
- 对“真实检索过但没有引用”的回答创建未覆盖提醒;
- 将 `resource://` 图片按私有 OSS 规则安全外发。
它不负责:
- WeKnora 文档、Chunk、向量、图谱、解析或模型运行;
- WeKnora Agent 的知识检索策略;
- 直接暴露 PostgreSQL、WeKnora 或对象存储到公网;
- 替代钉钉应用、机器人或群权限配置。
## 2. 架构
```text
钉钉用户 / 群
│ DingTalk Stream
▼
┌──────────────────────────────────────┐
│ dobotai-dingtalk 容器 │
│ - 消息解析、会话编排、卡片流式交付 │
│ - /think、/setting、首位管理员绑定 │
│ - 覆盖判定、Support Case、审计 │
└───────┬──────────────────┬───────────┘
│ │
│ HTTP Agent Chat │ PostgreSQL
▼ ▼
WeKnora 服务 DobotAI 独立数据库
- Agent/检索 - Turn / 会话 / 覆盖判定
- 文档/Chunk - Support Case / 反馈 / 设置
- 模型与解析
```
### 2.1 容器边界
| 资源 | 归属 | 是否由本容器创建/删除 |
| --- | --- | --- |
| `dobotai-dingtalk` | DobotAI应用进程 | 是,容器可重建 |
| DobotAI PostgreSQL | 独立数据服务 | 否,保留现有数据卷 |
| WeKnora | 独立知识服务 | 否 |
| `/var/lib/dobotai-test/secrets` | 宿主机密钥目录 | 仅挂载读写,不迁移、不输出 |
| `/etc/dobotai-test/dobotai.env` | 受保护运行配置 | Docker读取,脚本原子更新 |
测试环境的 PostgreSQL、WeKnora 已通过宿主机回环地址提供服务,因此 Compose 使用 `network_mode: host`。这不是新开公网端口:DobotAI仍按 `DOBOTAI_LISTEN_ADDR` 监听,默认是 `127.0.0.1:8090`。
### 2.2 容器安全属性
Compose 固定启用:
```text
容器名:dobotai-dingtalk
网络:host(仅兼容现有测试宿主机回环依赖)
运行身份:与原 dobotai-test 服务用户相同的 UID:GID
根文件系统:只读
临时写入:仅 /tmp tmpfs
额外权限:no-new-privileges
重启策略:unless-stopped
```
对应的关键 Compose 配置如下;不要为避免端口冲突额外添加 `ports:` 映射:
```yaml
services:
dobotai-dingtalk:
container_name: dobotai-dingtalk
network_mode: host
read_only: true
restart: unless-stopped
```
## 3. 安装前检查
安装操作人员需要具备测试服务器的 `sudo` 和 Docker 权限。开始前确认:
```text
1. 已构建或导入经审查的 DobotAI 镜像;
2. 现有 /etc/dobotai-test/dobotai.env 存在且权限为 0600;
3. 现有密钥目录 /var/lib/dobotai-test/secrets 存在;
4. DobotAI PostgreSQL 与 WeKnora 已健康;
5. 已记录当前原生服务二进制SHA和运行状态;
6. 如本版本包含 SQL 迁移,已先完成逻辑备份与迁移演练。
```
不要执行:
```text
docker compose down -v
docker volume rm / prune
删除 PostgreSQL / WeKnora 数据卷
将密钥、数据库连接串或 API Key 写入命令行、日志或 Git
```
## 4. 构建和导入镜像
在已审查且工作树干净的源码目录构建。示例中的值均为占位符:
```bash
docker build \
--build-arg VERSION=test-<commit-short> \
--build-arg COMMIT_SHA=<完整提交SHA> \
--build-arg BUILD_TIME=<UTC时间> \
-t dobotai-dingtalk:test-<commit-short> .
```
跨主机传输时先保存镜像归档并记录 SHA-256;测试服务器导入后必须复核归档哈希和镜像标签。生产不得在目标机重新编译,应使用已测试的同一镜像归档或不可变镜像摘要。
## 5. 安装容器资产(不切换服务)
将本目录、候选镜像和已核验的归档放到测试服务器的受控发布目录。确认镜像已经 `docker load` 后执行:
```bash
sudo DOBOTAI_IMAGE=dobotai-dingtalk:test-<commit-short> \
bash ./install-test.sh
```
该脚本会:
```text
1. 检查候选镜像、现有 env 与密钥目录;
2. 备份原生 DobotAI 二进制和 systemd Unit,并写入 SHA-256;
3. 安装 Compose、配置器、启动器和绑定脚本;
4. 生成权限 0600 的 /opt/dobotai-test/container/runtime.env;
5. 保持原生 dobotai-test.service 继续运行。
```
它不会读取或打印环境变量值、不会修改数据库、不会启动容器。
## 6. 配置并启动
日常只需要执行:
```bash
sudo dobotai-dingtalk-configure
sudo dobotai-dingtalk-bind-admin
```
第一条命令以隐藏输入方式更新 `/etc/dobotai-test/dobotai.env` 中的必填配置;不会将秘密传入命令行、终端输出或Git。环境文件写入成功后,它会受控停止原生 `dobotai-test.service`、启动 `dobotai-dingtalk`,并以 `/healthz` 验证。容器健康检查失败时自动停止容器并恢复原生服务。
第二条命令在已运行的容器内执行 `dobotai bootstrap-admin`。终端显示六码后,候选管理员私聊钉钉机器人:
```text
/setting <六码>
```
绑定成功后终端自动退出。该命令不会启动第二个钉钉 Stream 消费者。
## 配置项说明与示例
`sudo dobotai-dingtalk-configure` 会在每个输入项前显示相同的说明和示例。现有值永不显示;提示“已配置”时直接回车即可保留原值。秘密项以隐藏输入读取,以下示例均为脱敏占位符。
该命令交互更新 `/etc/dobotai-test/dobotai.env`。每项都会显示用途和脱敏格式示例;已配置的值永不回显,直接回车表示保留。
| 环境变量 | 用途 | 格式示例 |
| --- | --- | --- |
@@ -36,6 +160,121 @@ sudo dobotai-dingtalk-bind-admin
| `DINGTALK_CLIENT_ID` | 钉钉应用Client ID/AppKey | `dingxxxxxxxx` |
| `DINGTALK_CLIENT_SECRET` | 钉钉应用Client Secret/AppSecret | `<你的钉钉 AppSecret>` |
## 安装前置条件
保存成功后,配置器自动调用启动器:
安装脚本只接受已构建、已审查的本地镜像,并在切换前备份原生二进制与Systemd Unit。它不读取或打印环境文件中的值,也不停止旧服务。生产环境必须独立审查、备份和验证,不复用测试镜像以外的未验证构建。
```text
停止原生 dobotai-test.service
→ 启动 dobotai-dingtalk
→ 检查 http://127.0.0.1:8090/healthz
→ 健康成功后禁用原生服务
```
首次容器启动失败会恢复原生服务;容器版本升级失败会恢复上一容器镜像。
## 7. 首位管理员绑定
仅当该租户不存在有效管理员时执行:
```bash
sudo dobotai-dingtalk-bind-admin
```
终端会显示一个10分钟有效的随机六码。候选管理员必须私聊钉钉机器人发送:
```text
/setting <六码绑定码>
```
验证成功后,终端自动写入 `super_admin/active` 并退出。已有有效管理员时命令拒绝执行,防止借由该入口追加管理员或意外提权。
## 8. 覆盖判定与未覆盖提醒
覆盖判定基于真实的 `knowledge_searched` 工具事件和结构化引用,不按关键词猜测。
| 场景 | 覆盖结果 | 是否创建 Support Case |
| --- | --- | --- |
| 有引用 | `covered_has_references` | 否 |
| 实际检索过但无引用 | `uncovered_no_references` | 是 |
| 明确无权威知识/无答案 | `uncovered_explicit_no_answer` | 是 |
| 图片未检索、纯视觉识别 | `covered_visual_recognition` | 否 |
| 文本未检索、闲聊或普通非知识响应 | `covered_non_knowledge_response` | 否 |
因此“在吗”“你好”“谢谢”等未触发知识检索的文本不会产生未覆盖提醒;真正检索过但没有权威引用的问题仍会进入人工支持流程。
## 9. 数据库迁移门禁
DobotAI进程只连接数据库,**不会自动发现或执行 SQL 迁移**。包含新迁移的版本必须在容器替换前由发布流程显式完成:
```text
1. 对 DobotAI PostgreSQL 做逻辑备份;
2. 使用 pg_restore --list 验证备份非空;
3. 在事务中执行已审查的 .up.sql;
4. 向 dobotai_schema_migrations 写入对应 version/name/applied_at;
5. 查询约束、列或索引确认生效;
6. 再替换容器镜像并进行健康与业务验收。
```
`000021_coverage_non_knowledge_response_reason` 是一个示例:它只扩展 `coverage_decisions.reason_code` 的 CHECK 约束,不回写历史Turn、覆盖判定或Support Case。
## 10. 日常检查
```bash
# 健康检查
curl --noproxy '*' -fsS http://127.0.0.1:8090/healthz
# 运行版本
curl --noproxy '*' -fsS http://127.0.0.1:8090/version
# 容器状态与重启次数
sudo docker inspect -f '{{.Config.Image}}|{{.State.Running}}|{{.RestartCount}}' dobotai-dingtalk
# 最近日志(不要复制含敏感内容的原始上下文)
sudo docker logs --since 10m dobotai-dingtalk
```
验收至少应同时满足:
```text
容器 running,重启次数为0;
/healthz 返回 ok;
/version 的 commit_sha 与发布记录一致;
钉钉 Stream 仅启动一个消费者;
旧 dobotai-test.service 为 inactive + disabled;
目标业务路径已由真实钉钉消息验证。
```
## 11. 升级与回滚
### 升级
```text
构建/导入经审查的新镜像
→ 备份DobotAI PostgreSQL
→ 应用并记录必要迁移
→ 将 runtime.env 中的 DOBOTAI_IMAGE 更新为新标签
→ 执行 sudo dobotai-dingtalk-start
→ 健康、版本、日志、钉钉真实消息验收
```
注意拼写:数据库和应用名称是 `DobotAI`;上述流程中的镜像名为 `dobotai-dingtalk`。
### 自动回滚
启动器会保存替换前的容器镜像:
```text
首次容器化失败:停止候选容器,恢复原生服务;
后续容器升级失败:停止候选容器,恢复上一容器镜像。
```
数据库迁移不能仅靠容器回滚撤销。只有经过审查且已验证的 `.down.sql` 才可用于数据库回滚;任何数据恢复都必须先确认备份可用。
## 12. 明确非目标
```text
不容器化或重建 WeKnora;
不容器化或删除 DobotAI PostgreSQL;
不重新启用已删除的网页管理面;
不在生产环境复用测试凭据、测试镜像或未验收的迁移;
不把密钥、Token、连接串、钉钉凭据写入 Git、命令行或日志。
```