You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker中Directus触发Flask Webhook时出现连接拒绝问题

问题描述

我在Docker容器中运行了一个Directus实例,对应的docker-compose.yml配置如下:

services:
  directus:
    image: directus/directus:9.22.1
    ports:
      - 8055:8055
    volumes:
      - ./database:/directus/database
      - ./extensions:/directus/extensions
      - ./uploads:/directus/uploads
    environment:
      KEY: "some-key"
      SECRET: "some-secret"

      DB_CLIENT: "sqlite3"
      DB_FILENAME: "/directus/database/data.db"

      ADMIN_EMAIL: "admin@example.com"
      ADMIN_PASSWORD: "d1r3ctu5"

      CORS_ENABLED: true

我在Directus中配置了Webhook,当新条目创建时触发,将条目数据发送到我的Flask应用(目标地址设为http://localhost:8080/webhook)。Flask应用本该监听localhost:8080/webhook并将数据打印到命令行,但触发Webhook时收到Connection refused错误。我曾以为是Docker端口问题,已暴露8080:8080端口,但问题未解决。

Flask应用代码如下:

import paho.mqtt.client as mqtt

from flask import Flask, request, Response

app = Flask(__name__)

app.run(host='localhost', port=8080)


@app.route('/webhook', methods=['POST'])
def return_response():
    print(request.json)
    message = "An new entry was created!"
    print(message)

Webhook配置截图:
Webhook配置截图

错误日志如下:

directus-directus-1  | [11:52:22.159] WARN: connect ECONNREFUSED 127.0.0.1:8080
directus-directus-1  |     err: {
directus-directus-1  |       "message": "connect ECONNREFUSED 127.0.0.1:8080: connect ECONNREFUSED 127.0.0.1:8080",
directus-directus-1  |       "name": "Error",
directus-directus-1  |       "stack":
directus-directus-1  |           Error: connect ECONNREFUSED 127.0.0.1:8080
directus-directus-1  |               at AxiosError.from (file:///directus/node_modules/axios/lib/core/AxiosError.js:89:14)
directus-directus-1  |               at RedirectableRequest.handleRequestError (file:///directus/node_modules/axios/lib/adapters/http.js:516:25)
directus-directus-1  |               at RedirectableRequest.emit (node:events:513:28)
directus-directus-1  |               at eventHandlers.<computed> (/directus/node_modules/follow-redirects/index.js:14:24)
directus-directus-1  |               at ClientRequest.emit (node:events:513:28)
directus-directus-1  |               at Socket.socketErrorListener (node:_http_client:494:9)
directus-directus-1  |               at Socket.emit (node:events:513:28)
directus-directus-1  |               at emitErrorNT (node:internal/streams/destroy:151:8)
directus-directus-1  |               at emitErrorCloseNT (node:internal/streams/destroy:116:3)
directus-directus-1  |               at process.processTicksAndRejections (node:internal/process/task_queues:82:21)
directus-directus-1  |           caused by: Error: connect ECONNREFUSED 127.0.0.1:8080
directus-directus-1  |               at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1300:16)
directus-directus-1  |       "config": {
directus-directus-1  |         "transitional": {
directus-directus-1  |           "silentJSONParsing": true,
directus-directus-1  |           "forcedJSONParsing": true,
directus-directus-1  |           "clarifyTimeoutError": false
directus-directus-1  |         },
directus-directus-1  |         "transformRequest": [
directus-directus-1  |           null
directus-directus-1  |         ],
directus-directus-1  |         "transformResponse": [
directus-directus-1  |           null
directus-directus-1  |         ],
directus-directus-1  |         "timeout": 0,
directus-directus-1  |         "xsrfCookieName": "XSRF-TOKEN",
directus-directus-1  |         "xsrfHeaderName": "X-XSRF-TOKEN",
directus-directus-1  |         "maxContentLength": -1,
directus-directus-1  |         "maxBodyLength": -1,
directus-directus-1  |         "env": {},
directus-directus-1  |         "headers": {
directus-directus-1  |           "Accept": "application/json, text/plain, */*",
directus-directus-1  |           "Content-Type": "application/json",
directus-directus-1  |           "User-Agent": "axios/1.1.3",
directus-directus-1  |           "Content-Length": "324",
directus-directus-1  |           "Accept-Encoding": "gzip, deflate, br"
directus-directus-1  |         },
directus-directus-1  |         "url": "http://localhost:8080/webhook",
directus-directus-1  |         "method": "post",
directus-directus-1  |         "data": "{\"event\":\"items.create\",\"accountability\":{\"user\":\"d7c59a91-b6a8-4f1f-bcd6-95fc9d34c160\",\"role\":\"1ca3337b-aeed-4e5d-8076-06b949d59572\"},\"payload\":{\"publish_date\":\"2023-05-18T13:52:00+02:00\",\"title\":\"test\",\"author\":\"d7c59a91-b6a8-4f1f-bcd6-95fc9d34c160\",\"excerpt\":\"test\",\"body\":\"&lt;p&gt;test&lt;/p&gt;\"},\"key\":19,\"collection\":\"articles\"}"
directus-directus-1  |       },
解决方案

核心问题分析

  1. Docker网络隔离:Directus容器内的localhost指向容器自身,而非宿主机的localhost。当Directus请求http://localhost:8080时,是在容器内部寻找服务,而Flask应用跑在宿主机上,自然连接失败。
  2. Flask绑定地址错误:Flask设置host='localhost',仅监听宿主机的本地回环接口,容器无法通过宿主机IP访问到它。

修复步骤

步骤1:修改Flask应用配置

调整Flask的绑定地址为所有接口,并确保路由定义在启动服务之前,同时添加响应返回:

import paho.mqtt.client as mqtt

from flask import Flask, request, Response

app = Flask(__name__)


@app.route('/webhook', methods=['POST'])
def return_response():
    print(request.json)
    message = "有新条目创建!"
    print(message)
    return Response(status=200)  # 必须返回响应,否则Webhook会判定请求失败并重试

# 先定义路由再启动服务,避免路由未注册
if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)

步骤2:修改Webhook目标地址

根据操作系统选择合适的地址:

  • Linux/macOS/Windows:使用Docker内置的宿主机指向地址http://host.docker.internal:8080/webhook
  • 跨平台通用方式:直接使用宿主机的局域网IP(例如http://192.168.1.100:8080/webhook)

步骤3:检查防火墙设置

确保宿主机防火墙允许8080端口的入站请求:

  • Linux:检查ufw/firewalld是否开放8080端口
  • Windows/macOS:确认防火墙未阻止Flask应用的网络请求

额外场景处理(若Flask也在Docker中)

如果Flask应用同样运行在Docker容器中:

  1. 将Directus和Flask容器加入同一个Docker网络
  2. Webhook地址使用Flask容器的服务名(例如http://flask-service:8080/webhook)而非localhost

内容的提问来源于stack exchange,提问作者BranAndSceolan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 18:54:56