本文档由 AI 自动翻译。如有任何不准确之处,请参考 英文原版。Dify 1.17.1 将内置的 Weaviate 服务器镜像从
1.27.0 升级到 1.39.2,已有的 Weaviate 数据卷无法一步跨越这段版本差。本流程适用于 Dify 默认的单节点 Docker Compose 部署。全新部署会在空数据卷上直接使用新版本,无需执行本流程。
Weaviate 既未测试也不支持跨小版本升级,任何一个版本都可能包含磁盘数据迁移,而这类迁移要求上一个版本至少运行过一次。
受支持的升级方式是按顺序逐个小版本推进,每次都升到该小版本的最新补丁版本。下面给出完整阶梯,以及升级过程中最容易出问题的两个运维细节。
确认当前版本
从 Dify 仓库根目录进入docker 目录,后续步骤均在该目录下执行。Dify 默认的 docker-compose.yaml 不会为 Weaviate 映射宿主机端口,因此要在 Compose 网络内部执行检查,而不是访问宿主机的 localhost:
localhost 指的是 Weaviate 容器自身的回环地址,而不是宿主机。Weaviate 镜像内既没有 curl 也没有 Python,因此请求使用 busybox wget 发出,JSON 则由宿主机上的 Python 格式化。
如果显示 1.39.2,说明无需升级。当前版本为 1.27.0 时继续下文;如果显示升级阶梯中的某个中间版本,则从下一级继续;版本早于 1.27.0 时,先按照 Weaviate v4 迁移指南 完成迁移。
备份数据
对于 Docker 部署,最简单的备份方式是离线复制数据卷。先停止 Dify 的请求入口和 worker 服务以冻结写入,并保持这些服务停止,直到最后一级通过验证: 如果docker-compose.yaml 中没有定义 api_websocket,从下面的命令中去掉该服务名。
cp -a 会保留属主、权限和时间戳。用 sudo 执行的普通 cp -r 会改写这些属性,可能导致还原后的数据卷无法被 Weaviate 容器读取。
生产环境建议使用 Weaviate 的 备份模块 写入 S3、GCS 或 Azure。它生成的是可还原的快照,而不是原始目录副本,并且可以对运行中的实例执行。本地文件系统后端仅供开发使用。
逐个小版本升级
按顺序走完每个小版本,每次都停在该小版本的最新补丁版本上。
镜像仓库在第 1 步发生变化。现有部署从 Docker Hub 拉取
semitechnologies/weaviate,而阶梯使用 Weaviate 自有仓库 cr.weaviate.io/semitechnologies/weaviate,这也是 Dify 新版 Compose 文件所指向的地址。两者镜像相同,因此这里是有意同时变更仓库和版本。
表中的补丁版本为撰写时的最新值。对于中间各级,开始前先确认该小版本是否有更新的补丁,有则优先使用。
逐级升级还能缩小影响范围。某一级出问题时,只需回退一个版本,并且能立刻确定是哪个版本引入的问题,不必在一次跨越所有小版本的升级里二分排查。
紧跟最新版本才能持续拿到修复。Weaviate 只支持 最近的三个小版本,即当前版本及其之前的两个版本。更早的版本已终止支持,不再保证提供缺陷或安全修复。本次迁移完成后也要定期回看,及时升到当前补丁版本。
使用 Docker Compose 升级
Dify 在docker/docker-compose.yaml、docker/docker-compose.middleware.yaml 和 docker/docker-compose-template.yaml 三处固定 Weaviate 镜像版本。修改实际部署所用的文件,然后对每一级重复下面的循环。
1
设置下一级镜像标签
把
weaviate 服务改为下一个小版本的最新补丁,例如 image: cr.weaviate.io/semitechnologies/weaviate:1.28.16。2
优雅停止容器
docker kill 或 docker rm -f。强制杀死的代价参见 优雅停止 Weaviate。3
启动新版本
4
确认无误后再继续
进入下一级前,执行 每一步都要验证。
docker-compose.middleware.yaml 运行 Weaviate,同样的循环适用,只需显式指定文件:
优雅停止 Weaviate
这是最容易让检索失效、也最容易做错的一个细节。 Weaviate 把 HNSW 向量索引放在内存中,并通过提交日志写入磁盘。容器被强制杀死时(docker kill、docker rm -f、内存溢出被杀,或停止超过 Docker 的宽限期),提交日志可能残缺不全,尚未记录的对象也就不在图中。
丢的不是对象,而是图。在 1.39.2 上实测:向一个共 700 个对象的集合导入 500 个对象后立即强制杀死容器,结果如下:
20 个对象完好地存在于存储中,向量检索却触达不到。
危险之处在于没有任何提示。服务端没有报错,没有告警,关于提交日志更是只字未提,没有任何日志可供排查。而大多数人首先会看的对象数量,显示得完全正常。
它也不会自行恢复。重启之后、优雅停止再启动之后、再来一次之后,以及重新写入同样的对象之后,缺失的仍是同样这 20 个。要修复,需要在 Dify 中对受影响的知识库重新索引,让集合彻底重建。
因此这里的关键在于预防。使用
docker compose stop 或 docker compose down,两者都会发送 SIGTERM,并等待刷写完成。超时值 -1 会无限期等待,不会在超时后改用 SIGKILL:
limit 执行一次 near_vector 查询。返回结果更少,差值就是触达不到的对象。
每次重启后等待索引挂载
在阶梯上的所有版本中,/v1/meta 都会在容器启动约两秒后开始响应。集合挂载则更慢,从 1.31 起慢得多。在整个阶梯上实测,从 /v1/meta 可用到集合查询首次成功之间的间隔为:
在这个窗口内发出的查询不会提示「仍在启动」,而是提示数据不存在:
GET /v1/objects?class=...返回 404,响应体为空。- GraphQL 查询返回 422,内容为
no graphql provider present, this is most likely because no schema is present. Import a schema first!。
/v1/meta。
每一步都要验证
既要确认数据还在,也要确认检索可用。服务能启动并不代表索引是健康的。 先设置密钥和集合名称,再执行 4 项检查。Dify 为集合命名时,会把知识库 ID 中的连字符替换为下划线。从第 2 项检查的结果中复制准确名称,不要自行拼接:1.39.2 通过验证后,执行 docker compose stop -t -1 weaviate || exit 1。只还原临时修改的镜像配置,不要运行 Compose。然后按照 Docker Compose 升级说明 升级到 Dify 1.17.1。恢复服务前执行一次测试检索;能召回分段才说明向量索引存活,仅凭对象计数看不出这一点。
回滚失败的升级
启动 Dify 1.17.1 前,先把 Weaviate 镜像改回semitechnologies/weaviate:1.27.0,然后还原初始备份:
保持不变的部分
集合结构保持原样,因此无需重建索引,知识库照常可用。Dify 把每个数据集存为Vector_index_<dataset_id>_Node 集合,其中 ID 的连字符会替换为下划线,并使用自带命名向量 default。Dify 不设置距离度量,因此集合采用服务器默认的余弦距离。该结构在升级前后完全一致。
Python weaviate-client 同样无需处理。使用你所用 Dify 版本固定的客户端版本即可:Dify 1.14.0 至 1.16.1 为 4.20.5,1.17.0 至 1.17.1 为 4.22.0。两者都能与阶梯上的所有服务器版本配合工作,因此服务器可以独立于 Dify 单独升级。
如果运行的 Weaviate 服务器早于 1.27,或要从客户端 v3 迁移到 v4,请先参考 Weaviate v4 迁移指南,它覆盖 1.19.0 至 1.26.x 以及到 1.27 为止的 schema 迁移,之后再回到本文。