上周刚把自己手上的 Dify 社区版从 1.9.2 干到了 1.11.4,整个过程说实话比想象中折腾,但踩完坑之后回头梳理,发现流程本身是清晰的,真正容易翻车的地方就那么几个。这篇文章就把这次升级的完整过程、命令、备份方案、坑点全写出来,如果你也正在用 Docker Compose 部署 Dify,正准备从某个旧版本往上升,这篇应该能帮你省掉半天时间。
1. 要不要升:先看清 1.9.2 到 1.11.4 到底差了什么
1.1 这个版本跨度带来了什么
先别急着动手升级。升之前你得先搞清楚,从 1.9.2 到 1.11.4 中间到底发生了哪些变化。我升级之前特意去翻了官方 Release 记录和社区讨论,整理下来对日常使用影响比较大的有这几块。
首先是多租户支持。社区版从 1.10.0 开始加入了多租户能力,你可以在环境变量里开启 MULTI_TENANCY_ENABLED=true,开启后同一个部署实例下可以创建多个工作空间,每个空间之间的应用、知识库、成员权限都是隔离的。对于团队协作或者要给多个业务线提供 AI 能力的情况,这个变化是实质性的。1.9.2 的时代,社区版想要多租户只能靠多次部署或者自己改代码,现在不用了。
其次是 Agent 能力和工作流编排上的演进。1.10 和 1.11 这两个版本在 Agent 策略、工具调用、Chatflow 的多轮对话推理上都有不少改动。尤其是 Agent 策略这块,新版本对节点编排和工具选择的底层逻辑做了优化,意味着你在 1.9.2 里搭好的 Agent 工作流,升级后有可能出现节点配置不兼容或者行为变化的情况。
再就是知识库和检索方面的更新。1.11 对知识库的同步机制、分段清洗流程做了调整,另外在引用和检索的准确性上有优化。如果你之前在 1.9.2 里遇到知识库同步慢、召回效果不理想的情况,升级到 1.11 后会有改善,但前提是升级后你要把已有知识库重新触发一次同步,让新逻辑生效。
还有一个很容易忽略的点是模型管理。新版本在模型 Provider 的接入方式上也有调整,尤其是 Ollama、OpenAI Compatible 这类接口的配置项可能变化。升级后你可能会遇到模型列表变空、模型不存在之类的提示,这个后面我会专门说怎么排查。
1.2 升级的好处和风险
升级的好处不用多讲:bug 修复、安全补丁、新功能、性能优化。但升级本身也是有风险的。特别是跨了两个 minor 版本,风险集中在三块。
第一块是数据库迁移。Dify 升级过程中会自动执行数据库迁移脚本,这个脚本会改表结构。如果中途失败或者迁移脚本没跑完,API 服务起不来,整个平台就挂了。第二块是插件兼容性。1.9.2 时代装的插件,到 1.11.4 可能不兼容,轻则插件进不去,重则影响 Agent 工具调用。第三块是配置差异。新版本可能改了环境变量的默认值,或者新增了必填配置项,你没跟上就会遇到怪问题。
所以我的建议是:如果 Dify 只是你本地搭来玩玩、没有生产数据,那直接升级随便折腾;如果上面跑着业务,有用户在用,那就老老实实按我下面的流程走,先备份、再升级、后验证。
1.3 我为什么决定升级
我这边的情况是,Dify 上跑了几个知识库应用和 Agent 工作流,旧版本 1.9.2 遇到两个痛点:一是知识库同步在数据量大的时候经常卡住,要手动重启 worker 才能恢复;二是团队那边提出需要隔离不同业务线的应用和数据,旧版本做不到。
本来想直接等一个大版本,但社区版 1.10 的多租户和 1.11 的同步机制优化正好打在痛点上,于是决定升。如果你也是类似诉求,这个升级是值得的。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 升级前三个动作:环境盘点、完整备份、方案确认
2.1 环境盘点:先确认自己部署的是啥状态
很多人拿到升级教程就开始改镜像 tag,结果改了之后起不来,一排查才发现自己根本不是 Docker Compose 部署的,或者版本号都不对。所以先花五分钟盘点环境。
我在服务器上执行的第一条命令是:
bash复制docker --version
docker compose version
Dify 对 Docker 版本有要求,太老的版本跑不起来。我这台机器是 Docker 24.0.x,Compose v2.20 以上,满足要求。如果你用的还是 Docker 20.10 以前的版本,建议先升级 Docker 再动 Dify。
然后确认当前 Dify 版本。最简单的方法是看你 docker-compose.yaml 里的镜像 tag,或者直接看正在运行的容器镜像:
bash复制docker ps --format "table {{.Names}}\t{{.Image}}"
你会看到类似这样的输出:
code复制docker-api-1 langgenius/dify-api:1.9.2
docker-web-1 langgenius/dify-web:1.9.2
docker-worker-1 langgenius/dify-api:1.9.2
如果 Image 列显示的是 langgenius/dify-api:1.9.2,说明你的部署方式就是官方标准的 Docker Compose 部署,后面按我的流程走就行。如果显示的是自定义镜像名,说明你做了二次开发或者改了镜像,那就不能直接覆盖升级,得走二开合并流程。
接着确认数据目录。Dify 默认把数据挂在项目目录下的 volumes 文件夹里,包括上传文件、知识库文件、缓存等。你还需要确认 PostgreSQL 和 Redis 容器是否在运行:
bash复制docker ps | grep -E "db|redis|sandbox|ssrf|plugin"
Dify 1.9 之后的结构里包含这些容器:api、worker、web、db(PostgreSQL)、redis、sandbox、ssrf_proxy、plugin_daemon,以及可选的向量数据库容器(weaviate 或 qdrant)。升级前确认这些容器都在运行,说明当前平台状态是健康的。
最后检查磁盘空间。我这里要求至少预留 5GB 以上空闲空间,因为新镜像要拉取、旧镜像要保留用于回滚,数据库迁移过程也可能产生临时数据。用 df -h 看一眼即可。
2.2 完整备份:三步缺一不可
备份是升级前最重要的一步,没有之一。我见过太多人因为跳过了备份,升级失败后数据全丢,只能从头重建。Dify 的备份其实分三个部分:配置文件、数据目录、数据库。
配置文件备份最简单,把你整个 Dify 部署目录打包即可。通常部署目录里最关键的是 docker-compose.yaml、.env、volumes 这三个。我用的命令:
bash复制cd /opt/dify
tar czvf dify_1.9.2_backup_$(date +%Y%m%d).tar.gz \
docker-compose.yaml \
.env \
volumes
注意 .env 文件默认是隐藏的,tar 时要显式指定。这个 tar 包建议复制到另一台机器或者对象存储上,别留在同一块磁盘上,无意义。
数据库备份要用 PostgreSQL 自带的 pg_dump。Dify 默认数据库名是 dify,用户是 postgres。我用的命令是:
bash复制docker exec -t docker-db-1 pg_dump \
-U postgres \
-d dify \
-F c \
-f /tmp/dify_1.9.2.dump
执行完 docker cp docker-db-1:/tmp/dify_1.9.2.dump ./ 把 dump 文件拷贝到宿主机。这里用 -F c 自定义格式,方便后续 pg_restore,比纯 SQL 转储更灵活。
如果你用的向量数据库是 Weaviate,它的数据持久化在 volumes 里,打包 volumes 时已经带上了;如果是 Qdrant 也一样。这就是为什么 volumes 目录必须整体备份的原因。
备份完之后做一次验证:确认 tar 包能正常解压、dump 文件不是 0 字节。这一步花不了两分钟,但能避免你备份了个寂寞。
2.3 升级方案:直接跨版本升级还是分阶段
1.9.2 到 1.11.4 隔了两个 minor 版本,能不能直接跳?我的答案是能,但条件是你得接受可能出现的数据库迁移耗时和潜在兼容性风险。官方对跨版本升级没有明确禁止,社区里很多人都是从 1.8 甚至 1.7 直接升到 1.11 的,只要数据库迁移能跑完,基本没问题。
不过我的建议是不要直接在生产环境上跳。正确姿势是先在测试环境复现一遍升级流程,确认没问题再上生产。如果你没有测试环境,退而求其次——把生产环境完整备份之后,严格按照下面的步骤操作,中途不要做任何多余动作,一旦迁移失败马上回滚。
还有一个操作窗口的问题。数据库迁移在数据量大的时候可能需要几分钟到十几分钟,期间服务是中断的。尽量选在业务低峰期操作,如果你是个人使用那就无所谓了。
3. 核心升级实操:从 docker compose 配置到数据库迁移
3.1 更新 docker-compose.yaml 的镜像版本
这是整个升级的第一步,也是最容易被忽略细节的一步。Dify 的 docker-compose.yaml 里有多个服务的镜像需要改,不止 api 一个。
进入你的 Dify 部署目录,打开 docker-compose.yaml,把 langgenius/dify-api、langgenius/dify-web 等镜像的 tag 从 1.9.2 改成 1.11.4。具体哪些服务要改,我建议直接用 grep 查:
bash复制grep -n "image:" docker-compose.yaml
正常会看到:
yaml复制image: langgenius/dify-api:1.11.4
image: langgenius/dify-worker:1.11.4
image: langgenius/dify-web:1.11.4
注意 worker 和 api 用的是同一个镜像,只是容器启动命令不同,所以两个都要改。另外还有 langgenius/dify-sandbox:1.11.4、langgenius/dify-ssrf-proxy:1.11.4 之类的辅助服务,也一并改成新版本。
这里有个关键坑:如果你只改了 api 和 web 的镜像,worker 还是旧版本,那新旧版本之间通过数据库通信就可能出现不兼容,表现出来就是任务不执行、队列堆积、同步卡住。所以所有 Dify 官方镜像都必须同步升级,一个都不能漏。
改完之后先验证配置是否正确:
bash复制docker compose config --quiet
这条命令如果没输出,说明 YAML 语法和镜像配置没问题,可以继续。
3.2 同步更新 .env 环境变量
docker-compose.yaml 改完只是第一步,.env 文件里的环境变量也要跟着版本走。1.9.2 到 1.11.4 之间新增了一些配置项,直接沿用旧配置虽然大概率能启动,但新功能用不了,比如多租户。
先备份旧 .env,然后对比官方新版本的 .env.example。官方仓库在每次发版都会更新 docker/.env.example,你可以从 Docker Hub 拉镜像后,从镜像里提取参考,也可以去 GitHub 对应 release 标签下看。我这边主要关注几个变量:
bash复制# 多租户开关
MULTI_TENANCY_ENABLED=false
如果你想用多租户,就把这个改成 true。不开启的话保持默认即可,不影响其他功能。
还有一个比较重要的是 SECRET_KEY,这个必须保留你原来的值,千万不要重新生成,否则你之前存的敏感数据(比如 API Key)会解密失败,后果是所有模型配置全部丢失,用户也得重新登录。
再检查一下向量数据库相关的变量。1.9.2 默认用的是 Weaviate,如果你也是默认配置,升级后 VECTOR_STORE=weaviate 保持不变即可。如果你用的是 Qdrant,检查 QDRANT_URL 等配置是否还在。
新增的变量和改名过的变量,我建议用官方 .env.example 逐行和你现有的 .env 做 diff,把缺的补上,把废弃的删掉。这一步花的时间比改 docker-compose.yaml 多,但值得。
3.3 拉取新镜像并启动,盯着迁移日志看
配置都改好之后,正式进入升级动作。先拉取新镜像:
bash复制docker compose pull
这一步会花一点时间,镜像比较大,api 和 worker 加一起可能 1GB 以上。拉取过程中如果网络不好会超时,可以设置 Docker 镜像加速,或者拉取失败后重试即可。
镜像拉完,先别急着 up -d。我建议先把旧容器停掉,避免新旧版本混跑:
bash复制docker compose down
注意 down 默认不会删除数据卷,所以数据是安全的。如果它提示有 container 没被移除,可以用 docker compose rm 再清一下。
然后启动新版本:
bash复制docker compose up -d
启动完成后立刻看 api 容器的日志,数据库迁移的成败就体现在这里:
bash复制docker logs -f docker-api-1
正常情况下你会看到类似这样的输出:
code复制INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
INFO [alembic.runtime.migration] Running upgrade -> 1a0c2ad2e6b8, init
...
INFO [alembic.runtime.migration] Running upgrade xxxxx -> yyyyy, <migration message>
这个就是 Alembic 在跑数据库迁移。每一条 Running upgrade 都代表一次变更成功应用。如果看到 ERROR 或者 FAILED 出现,立即停住,不要强制重启,先看具体错误信息。
迁移跑完以后,api 容器会继续启动 Gunicorn,看到类似 Listening at: http://0.0.0.0:5001 的日志,说明 API 服务起来了。worker 容器会输出 Celery 的启动日志,看到 celery@... ready 就说明 worker 也正常。
最后检查 web 前端容器:
bash复制docker logs docker-web-1
如果正常会显示 Next.js 启动成功的日志。这时候打开浏览器访问你的 Dify 地址,如果页面能出来,说明升级流程基本走完了。
3.4 别急,还有几个服务要单独确认
整个 Dify 平台能正常访问,不代表所有功能都正常。有几个服务在升级后容易出问题,必须单独确认。
首先是 plugin_daemon。这个服务负责插件生命周期管理,如果它起不来,你在页面上安装插件会一直转圈或者报错。看日志的方式:
bash复制docker logs docker-plugin_daemon-1
确认没有报错后,进后台看插件列表是否正常加载。
其次是 sandbox 服务。如果你有写代码的节点(比如工作流里的代码执行节点),升级后一定要跑一遍测试,确认 sandbox 能正确执行代码。看日志:
bash复制docker logs docker-sandbox-1
还有 ssrf_proxy,这个负责转发 HTTP 请求,如果它挂了,知识库的网页抓取、工具调用都会失败。同样看下日志有没有异常。
我当时升级完,其他都正常,但 worker 容器一直在重启。排查了半天,发现是旧 Celery 队列里堆积了任务,新 worker 启动后尝试处理旧任务时崩溃。解决办法是清理队列:
bash复制docker exec -it docker-redis-1 redis-cli FLUSHALL
但注意,FLUSHALL 会清空 Redis 里的所有缓存,包括临时会话。我在业务低峰期执行,影响不大。如果你不确定是否要清,可以先 docker compose restart worker 试试,不行再清。
4. 升级后必做验证:功能清单和回滚预案
4.1 基础功能验证清单
升级不能以“页面能打开”作为成功标准,我每次都会跑一遍完整的验证清单。这些功能全部验证通过,才算真正升级成功。
第一项,登录和权限。用管理员账号登录后台,确认所有用户能正常登录,不是只有管理员能进。如果登录报错,大概率是会话密钥问题,检查 SECRET_KEY 是否保持一致。
第二项,模型配置。进入“设置 -> 模型供应商”,检查你之前配置的 OpenAI、Ollama、Azure OpenAI 等 Provider 是否还在。1.11 版本对模型管理有改动,有可能出现 Provider 在但模型列表为空的情况,需要重新填入模型名称和参数。特别是 Ollama,升级后要注意模型名是否正确,以及超时设置是否需要调大。
第三项,知识库。选一个已有的知识库,打开“文档”页,检查文档列表是否正常显示。然后触发一次同步,确认不再出现同步卡住。如果同步失败,检查向量数据库连接,以及 worker 日志。
第四项,工作流。打开你之前创建的工作流,逐个点击节点检查配置是否完好。重点看 Agent 节点和工具节点,因为这两个节点在新版本里改动比较大。如果打开工作流后提示 schema 错误,说明旧工作流的配置和新版本不兼容,可能需要重建节点或调整参数。
第五项,Chatflow 应用。发布一个 Chatflow 应用,跑一轮多轮对话,确认对话上下文能正确传递、知识库引用能生效。
第六项,API 调用。用一个实测的 API Key 调用一次 chat-messages 接口,确认接口正常返回。这一步能验证 API 服务的整体链路是否健康。
4.2 升级后最容易踩的几个坑
我在升级后遇到的第一个问题是前端白屏。页面打开是空白,控制台报一堆 404 或者 JS 加载失败。原因是浏览器缓存了旧版本的前端资源。解决方法很简单:清理浏览器缓存,或者用无痕窗口重新访问。如果你给用户提供服务,最好让用户也强制刷新一下。
第二个坑是模型 Provider 变成"未配置"。这个其实不是数据丢了,而是新版本改了模型配置的存储结构或者需要重新验证。解决方法:进入模型供应商页面,重新填入 API Key,保存后再看模型列表是否恢复。
第三个坑是知识库"同步中"卡住不动。1.9.2 时代这个 bug 很常见,升级后偶尔也会出现。排查思路:先看 worker 日志有没有报错,如果 worker 在处理任务,耐心等一会儿;如果 worker 没在跑,重启 worker 容器;如果重启也没用,就清理 Redis 里的任务队列再重启。
第四个坑是插件安装失败。1.11 的插件系统和 1.9 相比有更新,老插件可能没跟上。如果你在升级后安装新插件失败,先检查 plugin_daemon 日志,大多数情况是插件源连接不上或者版本不兼容。可以手动下载插件包再上传安装,绕开源仓库的连接问题。
第五个坑是 Ollama 模型处理超时。这个在社区里问得很多。升级后 Ollama 模型的响应超时设置可能被重置成默认值,如果你的本机或局域网内 Ollama 推理速度慢,就会频繁超时。解决方法:在模型供应商配置里把 Ollama 的超时时间调大,比如调到 300 秒。
4.3 数据验证和回滚预案
功能都验证完了,最后做一次数据完整性检查。对比升级前后数据库里的关键数据:应用数量、知识库数量、文档数量。我习惯这样快速验证:
bash复制docker exec -it docker-db-1 psql -U postgres -d dify -c "SELECT count(*) FROM apps;"
docker exec -it docker-db-1 psql -U postgres -d dify -c "SELECT count(*) FROM datasets;"
docker exec -it docker-db-1 psql -U postgres -d dify -c "SELECT count(*) FROM documents;"
数值和升级前对比,如果少了,说明迁移过程中丢了数据,立刻停服回滚。
回滚方案要提前准备好。我的做法是保留旧版本的镜像不清理,万一新版本跑不起来,直接改回旧的镜像 tag 再 docker compose up -d,数据库用备份的 dump 恢复。具体命令:
bash复制docker compose down
# 修改 docker-compose.yaml 中的镜像 tag 为 1.9.2
# 用备份文件恢复 volumes
docker compose up -d
docker exec -t docker-db-1 pg_restore -U postgres -d dify --clean /tmp/dify_1.9.2.dump
注意 pg_restore --clean 会删掉现有数据再重建,确保恢复到备份时间点。回滚后需要再重启 api 和 worker 让新旧代码状态一致。
我这里强烈建议:升级成功后别急着删除旧版本镜像,至少保留一周。等所有功能验证完毕、数据持续正常,再 docker image prune 清理不迟。
5. 常见问题与排查技巧实录
5.1 升级过程中最容易翻车的 5 个地方
我这次升级以及之前帮同事折腾的几次经历,总结下来最容易翻车的就是下面这几个点,几乎每个人都会踩中至少一个。
第一个是镜像 tag 只改了一部分。有人只改了 dify-api 的 tag,dify-worker 没改,结果升级后所有异步任务全部异常。排查起来很费劲,因为页面能打开,模型能配置,但知识库同步就是不工作。所以必须要确认所有服务用的都是同一版本镜像。
第二个是 docker compose down 的时候把数据卷一起删了。这个是最惨的,数据全没了。down 命令默认不删数据卷,但如果你用了 -v 参数就会删。升级时千万别带 -v,这个一定要记住。
第三个是数据库迁移时连接被重置。如果 API 容器启动时数据库还没有完全准备好,迁移就会失败。解决办法是反复重启 api 容器,或者等待数据库完全就绪后再启动。大部分人会在 up -d 后立即看日志,发现报错就慌,其实 docker compose restart api 多试几次往往就好了。
第四个是环境变量里 SECRET_KEY 被无意改动。很多人喜欢从官方 .env.example 复制新配置直接覆盖,结果把自己的密钥覆盖了。这里一定要用 diff 工具对比,只补新增项,保留原有值。
第五个是升级完发现自己旧知识库全不见了。这种情况通常不是数据丢了,而是向量数据库连接配置变了。1.11 版本默认向量数据库可能和旧版不一致,或者 VECTOR_STORE 环境变量被重置。检查 .env 里向量数据库相关配置,确认和升级前一致即可。
5.2 升级之后的一些运维体会
最后分享一点我这几次升级下来的心得体会。
Dify 这个项目迭代速度很快,社区版基本上每两个月就有一个新版本。如果一直不升级,积累的问题是越来越多的;但如果每个版本都追,运维成本也不低。我的习惯是:小版本(比如 1.11.x 到 1.11.y)尽量跟上,大版本跨度控制在两个 minor 以内,这样既有新功能,又不用每次大动干戈。
升级操作本身不复杂,耗时最多的是备份和验证。备份做扎实了,升级最大的风险就消除了。验证做全面了,就不会出现"升级完半个月才发现某个功能坏了"的尴尬。
还有一个小技巧,升级前先把当前版本的 docker-compose.yaml 和 .env 文件单独存一份在公司内部的文档系统里,标注好日期和升级目标版本。这样以后要回滚或者排查问题,你都有一份绝对的基线,不用靠回忆。
如果你正准备升级,我建议你按这篇的顺序走一遍,先把备份做扎实,再动手改配置。整个过程虽然看着步骤多,但真正操作起来,熟练的话半小时内能完成,不熟练也别急,多留出来两小时的验证时间,肯定能稳稳落地。
