大概半年前,我把一台自托管环境里的 Dify 从 1.8.1 升到了 1.9.2,部署方式是 Docker Compose,底层依赖是 PostgreSQL + Weaviate。说实话,一开始我以为这就是改个镜像版本号然后 docker compose up -d 的事,结果真动手才发现,1.8 到 1.9 的跨度远不止“又多了几个功能”,它牵扯到镜像组织方式、插件管理机制、数据库初始化逻辑,甚至 Weaviate 里已有索引的兼容性判断。整个过程走完后,我把踩过的坑、验证过的步骤和回滚逻辑整理成了一份可复用的升级 SOP。
这篇文章不打算复述官方文档里已经写清楚的内容,而是想把真正影响升级成败的那些“潜规则”讲透:备份到底该做到什么程度、编排文件为什么不能直接沿用旧的、数据库和向量库的启动顺序为什么敏感、以及升级后哪些现象说明你其实已经失败了。适合自己用 Docker Compose 部署 Dify、尤其是部署在 Linux 服务器或 Windows Docker Desktop 上的朋友参考,无论你现在是 1.8.x 还是更早版本,这套判断逻辑都能用。
1. 写在前面:这次升级真正的风险点在哪
1.1 小版本迭代背后隐藏的结构变化
很多自部署用户最容易犯的一个错误,是把 Dify 升级等同于“镜像版本号变大”。实际上,Dify 1.9 系列最大的架构级变化,是插件管理机制逐渐走向核心。以前模型供应商、工具节点这些东西基本是内置在 api / worker 镜像里的,升级后你会发现模型供应商的配置方式、工具节点的加载逻辑都开始由独立插件服务来管理。官方编排文件里也出现了更明确的插件守护进程服务,启动链路比 1.8 要长。
这会带来两个直接影响。第一,如果你的 1.8.1 里配置了很多自定义模型,而且是通过非标准方式接入的,升级后字段格式可能不兼容,肉眼可见的表象就是“模型供应商列表还在,但之前填的 API Key 或模型名称要么读不出来,要么页面直接报错”。第二,启动顺序更敏感了,插件的初始化发生在应用真正对外提供服务之前,如果数据库没有准备好或者网络解析失败,你看到的不是前台页面 500,而是 api 容器反复重启。
另一个隐藏风险是数据库侧的。Dify 的升级过程里,不可避免会触发 PostgreSQL 侧的 schema 变更,包括新增表、修改字段、写入迁移记录。1.8.1 到 1.9.2 跨了多个迭代,schema 迁移可能不是一次轻量“打补丁”,而是会创建不少新表结构。这个动作一旦执行,旧版本的代码往往无法继续兼容新库结构。所以如果你没提前做备份就贸然把镜像拉起来,万一中途失败想退回 1.8.1,会发现直接改回旧镜像也救不回来,因为数据库已经变了。这才是升级这件事最危险的地方。
1.2 什么情况下建议升级,什么情况下可以再等等
我个人的判断标准是:如果你当前 1.8.1 跑得很稳,知识库和工作流都是日常在用的生产数据,又没有迫切需要的安全修复或功能需求,那确实不必追赶版本。Dify 的迭代节奏很快,等一个更成熟的 patch 版本再升,能少踩不少社区反馈过的坑。
但如果你已经遇到了 bug,或者想体验 1.9 系列的新功能,那就别犹豫,尽快建立升级流程。注意这里说的“尽快”不是让你直接在生产环境操作,而是建议你先准备一套与生产环境尽量一致的测试部署,把升级流程在测试环境完整跑一遍,包括备份、拉新镜像、启动、验证和模拟回滚。我在实际操作中强烈建议至少做一次“全流程演练”,因为很多问题只有在真实数据规模下才会暴露,比如知识库分段多的时候 Weaviate 启动耗时、迁移脚本执行时间超过容器健康检查阈值等。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 动手之前的资产盘点:先把 PostgreSQL、Weaviate 和卷备份做完
2.1 PostgreSQL 逻辑备份是升级前唯一不可省的动作
在升级前,PostgreSQL 的逻辑备份不是可选项,而是硬性要求。Dify 的业务数据,包括用户、应用、工作流、知识库分段元数据,都存在 PostgreSQL 里。如果你只备份 docker volume 而没做逻辑备份,理论上也能用,但恢复的时候会比较痛苦,因为 volume 级别的文件备份需要保证数据库处于一致状态,实际操作中通常要停掉整个 Compose 环境才能做到。
所以我推荐用 PostgreSQL 自带的 pg_dump 做一次逻辑备份。假设你的 Compose 项目在 /opt/dify 目录下,推荐的命令是这样:
bash复制cd /opt/dify
docker compose exec -T db pg_dump -U postgres dify > backup_dify_1.8.1_$(date +%F).sql
注意我加了 -T 参数,也就是不分配伪终端,这样重定向出来的文件不会混入乱七八糟的控制字符。用户名 postgres 和数据库名 dify 不是固定的,要以你 .env 文件里的 DB_USERNAME、DB_DATABASE 实际值为准。备份完最好检查一下文件头部内容,确认不是空的,再看一眼文件大小是否在合理范围。我个人还会顺手再跑一次 wc -l,防止备份到一半网络中断导致 SQL 文件被截断。
如果你想把保险做到极致,可以再停掉 Compose 环境后对 PostgreSQL 的 volume 做一次文件级 tar 打包。命令大概是这样的:
bash复制docker compose down
docker run --rm -v dify_postgres_data:/data -v $(pwd):/backup alpine tar czf /backup/postgres_data_1.8.1.tar.gz -C /data .
但这组命令里的
