背景
在使用 Docker Compose 本地部署 Dify 时,由于网络环境原因(国内无法直连 GitHub 等海外资源),经常会遇到插件无法安装或更新的问题。
直觉告诉我们,给容器挂个代理不就行了?于是开始给容器配置 HTTP_PROXY,结果这才是噩梦的开始——不仅插件没更新成功,整个 Dify 还崩溃了,日志里满是 ERROR: Connection to sandbox failed。
经过反复查阅日志和排查,终于摸索出了 Dify 容器配置代理的“终极正确姿势”。今天把踩过的坑和最终方案总结下来,希望能帮大家少走弯路。
避坑指南:我踩过的那些坑
坑一:直接修改原生的 docker-compose.yaml
为了加环境变量,直接修改了官方的 docker-compose.yaml。
结果:下次执行 git pull 更新 Dify 代码时,直接产生代码冲突,或者配置被官方无情覆盖,还得重新改一遍。
坑二:NO_PROXY 没写全,导致内部微服务“迷路”崩溃
在给 api 和 worker 加上全局代理后,发现 Dify 界面报错卡死。查看 ssrf_proxy 容器的日志,发现大量致命错误:
2026/04/01 10:54:53| ERROR: Connection to sandbox failed
2026/04/01 10:54:53| Detected DEAD Parent: sandbox
原因:Dify 是微服务架构(API、Worker、DB、Redis、Sandbox 等)。如果你只设了代理,没把所有内部组件加进 NO_PROXY 白名单,内部请求(比如 ssrf_proxy 请求 sandbox 沙箱执行代码)就会被错误地发往外部代理服务器,从而导致内网断线。
坑三:只代理了 API,遗漏了核心的 plugin_daemon
把代理和 NO_PROXY 都配好,系统不崩溃了,但去点更新插件,依然一直在转圈失败。
原因:Dify 的插件下载逻辑并不在 api 容器里,而是在专门的 plugin_daemon 容器中。不给它配代理,插件永远拉不下来。
坑四:瞎写不存在的容器名
病急乱投医,往 compose 文件里加了不存在的 plugin_worker 等服务,结果启动时直接被 Docker 报错拦截:service has neither an image nor a build context specified。
最终完美方案
为了实现**“一次配置,永久生效,不惧更新更新,内部不崩溃,插件随便下”**,我们需要使用 Docker Compose 的 override (覆盖) 机制。
第一步:创建 Override 文件
进入你的 Dify Docker 部署目录(即 docker-compose.yaml 所在的目录),新建一个文件,命名为 docker-compose.override.yaml。
第二步:填入配置代码
将以下内容完全复制进去。注意把 192.168.1.17:7897 替换为你自己的代理所在的 IP 和端口(建议使用宿主机局域网 IP):
services:
# 1. API 服务:负责核心业务逻辑
api:
environment:
- HTTP_PROXY=http://192.168.1.17:7897
- HTTPS_PROXY=http://192.168.1.17:7897
# 极其关键:必须包含所有内部服务名及 Docker 默认网段
- NO_PROXY=localhost,127.0.0.1,api,worker,db,redis,ssrf_proxy,sandbox,weaviate,milvus,plugin_daemon,pgvector,web,etcd,elasticsearch,nginx,172.16.0.0/12,192.168.0.0/16
extra_hosts:
- "host.docker.internal:host-gateway"
# 2. Worker 服务:负责异步任务和数据处理
worker:
environment:
- HTTP_PROXY=http://192.168.1.17:7897
- HTTPS_PROXY=http://192.168.1.17:7897
- NO_PROXY=localhost,127.0.0.1,api,worker,db,redis,ssrf_proxy,sandbox,weaviate,milvus,plugin_daemon,pgvector,web,etcd,elasticsearch,nginx,172.16.0.0/12,192.168.0.0/16
extra_hosts:
- "host.docker.internal:host-gateway"
# 3. Plugin Daemon:负责真正执行插件下载与更新的服务
plugin_daemon:
environment:
- HTTP_PROXY=http://192.168.1.17:7897
- HTTPS_PROXY=http://192.168.1.17:7897
- NO_PROXY=localhost,127.0.0.1,api,worker,db,redis,ssrf_proxy,sandbox,weaviate,milvus,plugin_daemon,pgvector,web,etcd,elasticsearch,nginx,172.16.0.0/12,192.168.0.0/16
extra_hosts:
- "host.docker.internal:host-gateway"
第三步:应用配置
保存文件后,在当前目录执行以下命令重启容器:
docker compose up -d
Docker 会自动将官方配置和你的 override 配置合并并应用。现在,你的 Dify 既能正常访问外网更新插件,内部的微服务调用也稳如泰山了!
核心原理解析
如果你想知其然也知其所以然,可以看看这几个关键点:
- 为什么用
docker-compose.override.yaml? Docker Compose 启动时,如果发现目录下有这个 override 文件,会自动与原文件合并。这样做不破坏原文件,以后执行git pull更新 Dify 完全不受影响。 - 为什么
NO_PROXY这么长? 由于配置了全局代理,如果不排除内网,容器访问db、redis、sandbox时也会发往你的代理软件,代理软件根本不认识这些 Docker 内部的域名,直接导致断流。加入172.16.0.0/12则是为了兜底覆盖 Docker 的默认 IP 网段。 extra_hosts有什么用?- "host.docker.internal:host-gateway"这行代码会在容器内打通一条通往“宿主机”的网络捷径。不管你在 Windows、Mac 还是 Linux 上跑 Docker,它都能保证容器正确解析宿主机的 IP,防止找不到代理的情况。
结语
在使用复杂的开源微服务架构时,网络配置往往牵一发而动全身。希望这篇文章能帮你解决 Dify 插件更新卡顿和部署报错的烦恼!如果你有更好的配置思路,欢迎在评论区交流。
(写在最后:感谢这段排错过程,虽然被 AI 助手忽悠加了错误的容器名坑了一把,但最终还是揪出了所有网络连通性的细节,成就感满满!)