冬冬爱科学
发布于 2026-04-01 / 1 阅读
0
0

记一次踩坑:Docker 部署 Dify 配置代理的正确姿势(解决插件更新失败与 sandbox 报错)


背景

在使用 Docker Compose 本地部署 Dify 时,由于网络环境原因(国内无法直连 GitHub 等海外资源),经常会遇到插件无法安装或更新的问题。 直觉告诉我们,给容器挂个代理不就行了?于是开始给容器配置 HTTP_PROXY,结果这才是噩梦的开始——不仅插件没更新成功,整个 Dify 还崩溃了,日志里满是 ERROR: Connection to sandbox failed

经过反复查阅日志和排查,终于摸索出了 Dify 容器配置代理的“终极正确姿势”。今天把踩过的坑和最终方案总结下来,希望能帮大家少走弯路。


避坑指南:我踩过的那些坑

坑一:直接修改原生的 docker-compose.yaml

为了加环境变量,直接修改了官方的 docker-compose.yaml结果:下次执行 git pull 更新 Dify 代码时,直接产生代码冲突,或者配置被官方无情覆盖,还得重新改一遍。

坑二:NO_PROXY 没写全,导致内部微服务“迷路”崩溃

在给 apiworker 加上全局代理后,发现 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 既能正常访问外网更新插件,内部的微服务调用也稳如泰山了!


核心原理解析

如果你想知其然也知其所以然,可以看看这几个关键点:

  1. 为什么用 docker-compose.override.yaml Docker Compose 启动时,如果发现目录下有这个 override 文件,会自动与原文件合并。这样做不破坏原文件,以后执行 git pull 更新 Dify 完全不受影响。
  2. 为什么 NO_PROXY 这么长? 由于配置了全局代理,如果不排除内网,容器访问 dbredissandbox 时也会发往你的代理软件,代理软件根本不认识这些 Docker 内部的域名,直接导致断流。加入 172.16.0.0/12 则是为了兜底覆盖 Docker 的默认 IP 网段。
  3. extra_hosts 有什么用? - "host.docker.internal:host-gateway" 这行代码会在容器内打通一条通往“宿主机”的网络捷径。不管你在 Windows、Mac 还是 Linux 上跑 Docker,它都能保证容器正确解析宿主机的 IP,防止找不到代理的情况。

结语

在使用复杂的开源微服务架构时,网络配置往往牵一发而动全身。希望这篇文章能帮你解决 Dify 插件更新卡顿和部署报错的烦恼!如果你有更好的配置思路,欢迎在评论区交流。


(写在最后:感谢这段排错过程,虽然被 AI 助手忽悠加了错误的容器名坑了一把,但最终还是揪出了所有网络连通性的细节,成就感满满!)


评论