目录

一、问题背景

二、问题现象

1️⃣ MCP 发布失败

2️⃣ ssrf_proxy 容器日志异常

3️⃣ docker-api 容器日志

三、初步排查思路

MCP 是怎么工作的?

四、关键验证

1️⃣ curl 验证 MCP 接口是否存在

2️⃣ 容器内访问宿主机(失败)

3️⃣ufw 状态检查

4️⃣ iptables 规则检查

五、问题根因分析

❌ 错误认知

✅ 实际根因

六、解决方案

方案 A:使用 Docker 网桥网关 IP

方案 B:调整 iptables 允许 Docker 容器访问宿主机端口

方案 C:在 docker-compose.yml 添加 extra_hosts

核心问题总结


一、问题背景

在阿里云服务器(公网 IP:8.133.31.171)上,通过 Docker 部署了:

  • Dify 服务(对外端口:8083

  • 使用 Dify UI:

    • ✅ 可正常注册、登录

    • ✅ 可正常创建并执行工作流

    • 将工作流发布为 MCP 服务时失败

页面提示 MCP 服务部署失败,但 UI 信息较少,无法直接定位问题。

二、问题现象

1️⃣ MCP 发布失败

  • 工作流本身可运行

  • 一旦选择 “发布为 MCP 服务”

    • 后端直接报错

    • MCP 服务无法创建

MCP服务无法授权:

2️⃣ ssrf_proxy 容器日志异常

执行:

sudo docker logs -f --tail 10 docker-ssrf_proxy-1

关键输出类似:

TCP_MISS_TIMEDOUT/503 POST http://8.133.31.171:8083/mcp/server/o8VrG1O93pJy5kme/mcp

关键信息:

  • POST 请求

  • 目标地址:/mcp/server/.../mcp

  • 返回:503

  • 状态:TIMEDOUT

👉 说明请求根本没有成功到达 MCP 服务

3️⃣ docker-api 容器日志

sudo docker logs -f docker-api-1

关键日志:

HTTP Request: POST http://8.133.31.171:8083/mcp/server/.../mcp "HTTP/1.1 503 Service Unavailable"
 

👉 Dify API 服务在内部尝试回调 MCP 接口,但失败

三、初步排查思路

MCP 是怎么工作的?

当你在 Dify 中发布 MCP 服务时:

  1. Dify 后端会:

    • 在内部构造 MCP Server

    • 通过 HTTP POST 回调自身 /mcp/server/.../mcp

  2. 这个回调请求来自:

    • Docker 容器内部

  3. 目标地址却是:

    • 宿主机的对外地址(8083)

👉 关键问题转化为:

Docker 容器能否访问宿主机的 8083 端口?

四、关键验证

1️⃣ curl 验证 MCP 接口是否存在

curl -v http://8.133.31.171:8083/mcp/server/o8VrG1O93pJy5kme/mcp

返回:

HTTP/1.1 405 METHOD NOT ALLOWED

说明:

  • 接口存在

  • 但 MCP 接口只支持 POST(GET 返回 405 是正常的)

2️⃣ 容器内访问宿主机(失败)

docker exec -it docker-api-1 \
  curl -v -X POST http://host.docker.internal:8083/mcp/server/o8VrG1O93pJy5kme/mcp

结果:

Could not resolve host: host.docker.internal

关键结论:

Linux Docker 默认没有 host.docker.internal

docker exec -it docker-api-1 \
  curl -v -X POST http://8.133.31.171:8083/mcp/server/o8VrG1O93pJy5kme/mcp

结果:

3️⃣ufw 状态检查

  • ufw 没有启用,所以不会干扰。

  • 所以阻塞问题主要出在 Docker 自身的 iptables 规则。

4️⃣ iptables 规则检查

sudo iptables -L -n

关键内容:

Chain FORWARD (policy DROP)
Chain DOCKER
DROP all -- 0.0.0.0/0 0.0.0.0/0

📌 说明 Docker 默认阻断容器 → 宿主机转发流量

分析:

  • DOCKER 链默认规则是 DROP,FORWARD 默认 DROP。

  • 这意味着 Docker 容器访问宿主机的端口 可能被阻止,尤其是从容器网桥(172.19.0.0/16)到宿主机的 8083 端口。

  • DOCKER-USER 链是空的,说明你没有显式放行规则。

✅ 结论:即使宿主机防火墙 (ufw) inactive,Docker 默认的桥接防火墙规则可能阻止容器访问宿主机服务。

五、问题根因分析

❌ 错误认知

  • 以为容器访问宿主机公网 IP 没问题

  • 以为 ufw 未开启就没有防火墙问题

✅ 实际根因

MCP 部署失败的根本原因是:

容器内部无法访问宿主机的 Dify MCP 服务端口(8083),导致 POST 请求超时,返回 503。

  • 并非 Dify 本身或 plugin_daemon 的问题。

  • 主要因素:Docker 默认网络与 iptables 配置阻止容器访问宿主机端口。

Docker 容器无法访问宿主机 8083 端口

原因包括:

  1. Linux 下不存在 host.docker.internal

  2. Docker 默认 FORWARD / DOCKER 链是 DROP

  3. 使用公网 IP 会触发 NAT 回环问题

  4. MCP 部署是容器内部 HTTP POST 回调

最终结果:

  • MCP POST 请求超时

  • ssrf_proxy 返回 503

  • MCP 服务创建失败

六、解决方案

方案 A:使用 Docker 网桥网关 IP

思路:让 Docker 容器通过 Docker 网桥 IP 访问宿主机

① 查宿主机 docker0 网桥 IP:

ip addr show docker0

一般为:inet 172.17.0.1/16

② 测试容器访问,如果能返回 405/200,说明通路正常:

docker exec -it docker-api-1 curl -v -X POST http://172.17.0.1:8083/mcp/server/o8VrG1O93pJy5kme/mcp

dify中MCP服务可配置:

将主机IP替换为Docker 网桥 IP

方案 B:调整 iptables 允许 Docker 容器访问宿主机端口

② 放行 Docker → 宿主机 8083(关键)

# 放行 docker0 网桥到宿主机的 8083
sudo iptables -I DOCKER-USER -i docker0 -p tcp --dport 8083 -j ACCEPT
sudo iptables -I FORWARD -i docker0 -o docker0 -p tcp --dport 8083 -j ACCEPT
  • 添加后再次测试容器 curl。

  • 可以考虑将规则写入 /etc/iptables/rules.v4 永久保存。

方案 C:在 docker-compose.yml 添加 extra_hosts

如果不想改 iptables,可以在 docker-api-1 服务中添加:

services:
  api:
    ...
    extra_hosts:
      - "host.docker.internal:172.17.0.1"

然后容器内部就可以用 host.docker.internal 访问宿主机。

推荐做法

  • Linux 宿主机 Docker,最简单可行的方式是:

    1. 使用宿主机 Docker 网桥 IP(如 172.17.0.1)。

    2. 确保 iptables DOCKER-USER 链放行。

  • 不依赖 host.docker.internal(只在 Mac/Windows 可用)。


核心问题总结

  1. 容器内部无法解析 host.docker.internal → 容器无法通过该方式访问宿主机。

  2. Docker 默认桥接网络的 iptables 规则对容器访问宿主机 8083 有阻断(FORWARD DROP + DOCKER 链 DROP)。

  3. 因此,MCP 服务部署请求从容器发出时,无法到达宿主机 8083 → 超时 → ssrf_proxy 和 docker-api 日志显示 503。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐