InSoulForge + NapCat Docker 部署指南

项目开源地址:https://github.com/DreamDonghao/insoulforge

本文以一台全新安装的 Ubuntu 24.04/26.04、amd64/arm64 主机为例,从安装 Docker 到在 QQ 群中收到机器人回复。主方案使用 NapCat 的 OneBot 11 正向 WebSocket 服务端,由 InSoulForge 主动连接。无需在宿主机安装 C++、Node.js 或数据库。

本文默认拉取 Docker Hub 上的 dreamdonghao/insoulforge:latest。项目的发布工作流使用 docker/metadata-action:正式 SemVer 标签构建时会生成版本号、主次版本号、SHA 和 latest 标签,并将镜像推送到 Docker Hub 与 GHCR。latest 是发布时更新的标签,不会随着 GitHub Release 页面变化而自行移动;需要固定部署版本时,把下文镜像名改为已经发布的具体版本标签或摘要。NapCat 镜像同样可以在验证后固定版本或摘要。Docker metadata-action 的 latest 规则

1. 准备

  • 一台可访问 Docker Hub、NapCat/QQ 和所选模型 API 的 Linux 主机;可以使用 sudo。
  • 一个供机器人登录的 QQ 号,且该账号已加入需要使用的群。
  • 至少一个兼容项目请求格式的聊天模型 API。Router 和 Executor 都必须配置;视觉模型建议配置,深度思考模型和 Embedding 可后补。
  • 预留宿主机的 7778(InSoulForge 管理后台)和 6099(NapCat WebUI)端口。本文只绑定到宿主机 127.0.0.1,远程管理使用 SSH 端口转发。NapCat 的 3001 仅在容器网络内使用,不对外发布。

NapCat 官方 Docker 镜像支持 Linux amd64/arm64,持久化目录分别为 /app/napcat/config 和 /app/.config/QQ。NapCat-Docker 官方说明

2. 安装 Docker Engine

如果已经安装 Docker Engine,可跳到第 3 节。全新 Ubuntu 按 Docker 官方 Ubuntu 安装文档配置官方软件源:

sudo apt-get update
sudo apt-get install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

sudo tee /etc/apt/sources.list.d/docker.sources >/dev/null <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF

sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin
sudo systemctl enable --now docker
sudo docker version

选择 Compose 方式时,再安装插件并确认版本:

sudo apt-get install -y docker-compose-plugin
sudo docker compose version

如果主机已有 docker.io、旧版 docker-compose 或其他冲突包,先按 Docker 官方文档处理冲突,再安装;不要直接混装。以下命令统一使用 sudo docker,不要求把当前用户加入具有高权限的 docker 组。

3. 启动容器:任选一种方式

方式 A:Docker Compose

在部署主机执行。目录名可自行调整,但后续命令需在同一目录下执行:

umask 077
mkdir -p "$HOME/insoulforge-deploy"/{data,napcat/config,napcat/QQ}
cd "$HOME/insoulforge-deploy"
printf 'NAPCAT_UID=%s\nNAPCAT_GID=%s\n' "$(id -u)" "$(id -g)" > .env
chmod 600 .env

新建 compose.yaml,内容如下:

services:
  napcat:
    image: mlikiowa/napcat-docker:latest
    restart: unless-stopped
    environment:
      NAPCAT_UID: ${NAPCAT_UID}
      NAPCAT_GID: ${NAPCAT_GID}
    ports:
      - "127.0.0.1:6099:6099"
    volumes:
      - ./napcat/config:/app/napcat/config
      - ./napcat/QQ:/app/.config/QQ

  insoulforge:
    image: dreamdonghao/insoulforge:latest
    restart: unless-stopped
    depends_on:
      - napcat
    ports:
      - "127.0.0.1:7778:7778"
    volumes:
      - ./data:/app/data

Compose 会为两个服务创建同一内部网络;InSoulForge 可以通过服务名 napcat 访问 NapCat 的 3001 端口,不要在 InSoulForge 配置中填写 127.0.0.1:3001,那会指向 InSoulForge 容器自身。Dockerfile 的工作目录是 /app,配置与数据库位于 /app/data。

先检查 Compose 文件,再启动:

sudo docker compose config --quiet
sudo docker compose pull
sudo docker compose up -d
sudo docker compose ps

若 dreamdonghao/insoulforge:latest 拉取失败,先检查 GitHub Actions 构建和 Docker Hub 的镜像标签;也可将镜像名改为 ghcr.io/dreamdonghao/insoulforge:latest 后重试。确实没有可用镜像时,参见第 10 节的源码构建方法。

首次启动会自动创建 ./data/config.json 和 ./data/insoulforge.db。日志会输出到容器标准输出,也会写入容器内的 /app/logs/bot.log;本方案不备份文件日志,删除并重新创建容器后不能依赖旧日志仍可恢复。当前镜像在 Dockerfile 中声明了 /app/logs 和 /app/uploads 为 VOLUME,因此不写 Compose 挂载也可能产生匿名卷;这不等于业务数据需要备份。此时还没有设置 OneBot 和模型参数,机器人不能正常对话。

方式 B:只使用 Docker 命令,不使用 Compose

不要与方式 A 同时执行,否则容器会争用宿主机端口。完成第 2 节的 Docker Engine 安装后,在部署主机运行:

umask 077
mkdir -p "$HOME/insoulforge-deploy"/{data,napcat/config,napcat/QQ}
cd "$HOME/insoulforge-deploy"
sudo docker network create insoulforge-net
sudo docker pull mlikiowa/napcat-docker:latest
sudo docker pull dreamdonghao/insoulforge:latest

sudo docker run -d \
  --name napcat \
  --restart unless-stopped \
  --network insoulforge-net \
  -e NAPCAT_UID="$(id -u)" \
  -e NAPCAT_GID="$(id -g)" \
  -p 127.0.0.1:6099:6099 \
  -v "$PWD/napcat/config:/app/napcat/config" \
  -v "$PWD/napcat/QQ:/app/.config/QQ" \
  mlikiowa/napcat-docker:latest

sudo docker run -d \
  --name insoulforge \
  --restart unless-stopped \
  --network insoulforge-net \
  -p 127.0.0.1:7778:7778 \
  -v "$PWD/data:/app/data" \
  dreamdonghao/insoulforge:latest

sudo docker ps --filter name=napcat --filter name=insoulforge

两个容器位于同一用户自建网络,napcat 容器名可作为 DNS 名称,因此第 5 节的 OneBot 地址仍填写 ws://napcat:3001。NapCat 的 WebSocket 服务尚未配置时,InSoulForge 可能暂时重连,这是正常现象。若 InSoulForge 镜像拉取失败,可改用 ghcr.io/dreamdonghao/insoulforge:latest,并在上述 docker run 命令中使用同一镜像名。首启配置、数据库和非持久化日志的说明与方式 A 相同。

后续章节中的 Compose 命令,对应的纯 Docker 命令如下;docker logs 不要求当前目录是部署目录:

Compose 命令纯 Docker 命令
sudo docker compose logs --tail=100 napcatsudo docker logs --tail=100 napcat
sudo docker compose logs --tail=120 insoulforgesudo docker logs --tail=120 insoulforge
sudo docker compose pssudo docker ps --filter name=napcat --filter name=insoulforge
sudo docker compose stopsudo docker stop insoulforge napcat
sudo docker compose up -d(已创建容器时)sudo docker start napcat insoulforge

第 9 节的备份和更新操作需要按本方式的独立命令执行,不要对没有 compose.yaml 的目录运行 Compose 命令。

4. 登录 NapCat 并创建正向 WebSocket 服务

在主机本地浏览器打开 http://127.0.0.1:6099/webui。如果从另一台电脑管理服务器,先在自己的电脑建立 SSH 转发:

ssh -L 6099:127.0.0.1:6099 -L 7778:127.0.0.1:7778 用户名@服务器地址

保持这个 SSH 会话运行,然后仍在自己电脑的浏览器访问上述 127.0.0.1 地址。不要为了方便把 NapCat WebUI 或 InSoulForge 管理后台直接暴露到公网。Docker 发布的端口可能绕过部分主机防火墙规则,安全边界应以绑定地址和网络策略为准。Docker 官方安装文档的防火墙说明

查看 NapCat 启动日志取得 WebUI 登录令牌或登录地址:

sudo docker compose logs --tail=100 napcat

在 NapCat WebUI 的 QQ 登录页面用手机 QQ 扫码,确认登录的是机器人账号。首次登录或扫码后 WebUI 令牌可能刷新,若原令牌失效,重新查看 NapCat 日志或挂载的 ./napcat/config/webui.json。按照 WebUI 提示修改初始登录密码。NapCat WebUI 官方配置指南

在 NapCat 的 网络配置 → 新建中创建并启用一项:

选项值
类型WebSocket 服务端,不是 WebSocket 客户端
监听地址0.0.0.0,供同一 Docker 网络中的 InSoulForge 连接
端口3001
消息上报格式array
Access Token自己生成的一段较长随机字符串,记下供下一节使用
启用保存时启用,或保存后手动启用

array 格式很重要:当前项目按 OneBot 消息段数组解析文字、@、图片等内容。正向 WebSocket 的事件和动作共用这一条连接,不需要额外创建 HTTP 客户端、HTTP 服务端或反向 WebSocket 客户端。若 NapCat 之前已经配置了 HTTP 上报,先关闭它,避免同时走两条传输链路。NapCat 官方文档区分这四种网络类型,并列出了 WebSocket 服务端的监听地址、端口、上报格式和令牌字段。NapCat WebUI 官方配置指南

WebUI 登录令牌与这里的 OneBot Access Token 不是同一个凭据;两者不要混用。

5. 登录 InSoulForge 并配置 OneBot

获取 InSoulForge 本次启动生成的管理后台令牌或自动登录链接:

sudo docker compose logs --tail=120 insoulforge

日志中可找到 管理后台访问令牌 和 index.html#token=...。在浏览器打开 http://127.0.0.1:7778/index.html#token=实际令牌。通过 SSH 转发时也使用本机的 127.0.0.1:7778。登录后令牌会从地址栏清除;令牌只存在当前进程内,每次重启都重新生成,旧登录会话随之失效。不要将含令牌的链接发送给他人。

进入 OneBot 配置,填写:

字段填写值
Bot QQ 号NapCat 当前登录的机器人 QQ 号,必须完全一致
Bot 名称机器人在群里的称呼
传输方式WebSocket
WebSocket 服务地址ws://napcat:3001
Access Token第 4 节 NapCat WebSocket 服务端设置的令牌

保存后项目会更新内存配置并重新建立 OneBot WebSocket 连接,不必仅为保存这一项而重启容器。确认 InSoulForge 日志出现 OneBot WebSocket 已连接,管理后台首页显示 OneBot WebSocket 已连接。首页另一项“WebSocket”可能表示浏览器与管理后台的连接,两者不是同一链路。连接失败时先检查服务端类型、地址、端口和令牌。

配置文件实际保存在宿主机 ./data/config.json 的 qq 部分。默认值是 oneBotTransport: "websocket",但默认地址 ws://127.0.0.1:3001 只适合 NapCat 与程序在同一网络命名空间运行;本文两种 Docker 部署方式都必须改成 ws://napcat:3001。若选择手工修改 JSON,先停止容器,修改后再启动,避免运行中的内存配置与磁盘文件不一致。

6. 配置模型

在后台 LLM 配置逐项填写真实服务提供商给出的 API Key、Base URL、Path 和模型 ID:

配置项是否必需用途
Router必需决定当前消息是否需要回复
Executor必需生成回复并调用工具
Image建议图片和 GIF 的视觉描述;不配置时相关内容无法被正常识别
Executor 思考可选deep_think 工具调用的模型,不是所有消息都使用
Embedding可选长期记忆向量化与相似度召回

聊天模型的 URL 可按下面方式拆分,示例域名与模型名不能直接使用:

提供商完整接口: https://api.example.com/v1/chat/completions
baseUrl:        https://api.example.com/v1
path:           /chat/completions
model:          提供商实际模型 ID
apiKey:         提供商实际密钥

程序会把 baseUrl 的路径部分与 path 组合;不要在两处都填写 /v1。Embedding 通常使用 /embeddings 路径。maxTokens、温度和 topP 可先保留默认值,若模型把思考内容计入输出上限,按实际响应再提高对应模型的 maxTokens。模型密钥会写入 ./data/config.json,应保护该目录,且不要把文件复制进仓库或公开日志。

后台保存模型配置后会更新运行中的配置。首次验证先填 Router 和 Executor;要测试图片或 GIF,再填支持视觉输入的 Image 模型。Embedding 留空不会阻止普通对话,但长期记忆向量化和召回不可用。

7. 启用会话并验证

机器人默认只处理已启用的会话。进入后台 会话管理 → 添加会话,选择“群聊”并填写群号;私聊则选择“私聊”并填写对方 QQ 号。确认该会话状态为“启用”。如需通过 QQ 命令管理,先在后台的 访问管理添加管理员 QQ;首次部署不必依赖群内命令完成启用。

在已启用的群里发送 @机器人 你好。依次检查:

  1. NapCat 已登录正确 QQ 账号,且该账号在群内。
  2. 后台首页的 OneBot WebSocket 显示已连接。
  3. 会话管理中出现最新用户消息。
  4. 运行日志出现消息预处理、Router/Executor 及 OneBot 发送记录。
  5. 群内收到回复;用量统计中有对应模型调用。

Router 对普通群消息可以选择不回复,因此首次联通测试请用 @机器人,不要只发普通文本。若图片测试失败,先确认 Image 模型已配置且支持视觉输入,再看日志中的媒体下载或视觉请求错误。

8. 常见故障

现象优先检查
NapCat WebUI 无法打开sudo docker compose ps、logs napcat;确认 SSH 转发仍在运行,WebUI 实际端口以 NapCat 日志为准
InSoulForge 后台无法打开logs insoulforge、宿主机 7778 是否被占用、SSH 转发是否仍在运行
日志不断提示 WebSocket 断开或重连NapCat 应创建“WebSocket 服务端”;确认其已启用、监听 0.0.0.0:3001,项目地址为 ws://napcat:3001,双方 OneBot Token 一致
NapCat 有消息但项目看不到确认 WebSocket 已连接、NapCat 的消息上报格式为 array、机器人 QQ 与后台配置一致;不要把正向 WebSocket 配成客户端
消息进来了但不回复确认机器人在后台处于运行中、会话已启用、Router 和 Executor 已配置;先用 @机器人 测试,再看 Router/Executor 错误日志
HTTP 上报或 409 相关提示WebSocket 模式下关闭 NapCat 旧的 HTTP 客户端上报,避免双链路;只保留一项正向 WebSocket 服务端
模型接口返回 404核对 baseUrl 与 path 的拼接结果,避免重复 /v1、漏写 /chat/completions 或使用不兼容接口
重启后无法再登录后台InSoulForge 管理令牌每次启动重新生成;重新查看 logs insoulforge

只查看最近日志(注意日志中可能包含敏感信息,不要整段公开):

sudo docker compose logs --tail=150 insoulforge
sudo docker compose logs --tail=150 napcat
sudo docker compose ps

使用方式 B 时,分别执行 sudo docker logs --tail=150 insoulforge、sudo docker logs --tail=150 napcat 和 sudo docker ps。

9. 备份、更新和停止

需要备份的数据包括 ./data(配置、SQLite 数据库和图片描述缓存),以及 ./napcat/config 和 ./napcat/QQ(NapCat 配置与 QQ 登录态)。当前项目没有使用 uploads 保存业务数据;文件日志仅用于排障和恢复后台历史日志,按需单独持久化即可。备份数据库时先停止服务,避免复制到写入中的 SQLite 文件:

cd "$HOME/insoulforge-deploy"
sudo docker compose stop
sudo tar -czf "$HOME/insoulforge-backup-$(date +%Y%m%d-%H%M%S).tar.gz" \
  data napcat .env compose.yaml
sudo docker compose up -d

更新前先备份,再确认目标镜像已发布。使用 latest 时直接拉取并重建容器;固定版本时先修改 compose.yaml 中的版本号,再执行:

sudo docker compose pull
sudo docker compose up -d
sudo docker compose ps
sudo docker compose logs --tail=100 insoulforge

正常停止可使用 sudo docker compose stop。不要删除上述挂载目录;不要用 docker compose down -v 代替日常停止。重建容器会重新生成 InSoulForge 管理令牌,但不会清除已挂载的数据目录。

**方式 B(纯 Docker)**的备份不需要 .env 或 compose.yaml:

cd "$HOME/insoulforge-deploy"
sudo docker stop insoulforge napcat
sudo tar -czf "$HOME/insoulforge-backup-$(date +%Y%m%d-%H%M%S).tar.gz" data napcat
sudo docker start napcat insoulforge

更新 InSoulForge 时,先按上面的方法备份,再拉取镜像并用第 3 节方式 B 中完全相同的网络、端口和数据挂载参数重新创建容器;仅执行 docker restart 不会应用新镜像:

cd "$HOME/insoulforge-deploy"
sudo docker pull dreamdonghao/insoulforge:latest
sudo docker stop insoulforge
sudo docker rm insoulforge
sudo docker run -d \
  --name insoulforge \
  --restart unless-stopped \
  --network insoulforge-net \
  -p 127.0.0.1:7778:7778 \
  -v "$PWD/data:/app/data" \
  dreamdonghao/insoulforge:latest
sudo docker logs --tail=100 insoulforge

如需更新 NapCat,也先备份,再拉取新镜像、停止并移除旧 napcat 容器,然后照第 3 节方式 B 的 NapCat docker run 命令重建。日常停止与重新启动分别使用 sudo docker stop insoulforge napcat 和 sudo docker start napcat insoulforge;不要删除 data、napcat 目录或 insoulforge-net 网络。重建 InSoulForge 后管理令牌会改变,需重新查看日志。

10. 可选:没有发布镜像时从源码构建

只有镜像仓库没有目标版本时才需要这一步。Dockerfile 自带后端与前端的构建环境,宿主机只需再安装 Git:

sudo apt-get install -y git
cd "$HOME/insoulforge-deploy"
git clone https://github.com/DreamDonghao/insoulforge.git app-source
git -C app-source checkout v1.4.1
sudo docker build -t local/insoulforge:1.4.1 ./app-source

方式 A:把 compose.yaml 中 InSoulForge 的 image: 改为 local/insoulforge:1.4.1,再执行 sudo docker compose up -d。方式 B:在第 3 节或第 9 节的 InSoulForge docker run 命令中把镜像名换为 local/insoulforge:1.4.1;已有容器需先停止并移除。若目标标签尚未推送,必须明确选用你实际要部署的提交,不要把未验证的默认分支当作同一版本。

11. 可选:改用 HTTP 传输

项目也支持 HTTP,但同一时间只能使用 HTTP 或 WebSocket 一种方式。若确实要切换,在 NapCat 新建并启用 HTTP 服务端(例如 0.0.0.0:3000,供项目调用动作 API)和 HTTP 客户端(上报地址 http://insoulforge:7778/,消息格式 array);关闭原 WebSocket 服务端。项目后台选择 HTTP,并将 HTTP 服务地址填为 http://napcat:3000,保存后检查状态和消息。HTTP 上报端点在当前代码中不校验 OneBot Token,因此保持两个服务只在受控的 Docker 内部网络互通,不要对公网开放 7778 或 NapCat API 端口。主方案无需进行本节操作。

依据

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐