You need to enable JavaScript to run this app. Docker部署Node-RED等多容器搭配Nginx反代后前端WebSocket无法接收数据
优惠活动
大模型
产品
解决方案
定价
更多

Docker部署Node-RED等多容器搭配Nginx反代后前端WebSocket无法接收数据

Nginx反向代理Docker容器化服务时WebSocket连接故障排查

部署架构说明

  • 基于Docker Compose编排3个独立容器服务:Node-RED、InfluxDB、基于nginx:alpine镜像构建的静态网页服务。网页内置图片资源,通过WebSocket通道接收Node-RED推送的数据,动态切换页面展示的图片
  • 宿主机侧部署独立非容器化Nginx,搭配Let's Encrypt证书,对上述3个容器服务做反向代理
  • 故障触发条件:所有服务未做容器化部署时流程可正常运行,全量迁移到Docker容器后,WebSocket链路无法正常接收推送数据

问题场景截图

前端原有WebSocket连接逻辑代码

function startConnect() {
    document.getElementById('dt').click();
    socket = new WebSocket("ws://mywebsite.com:1880/ws/test");
    socket.onmessage = function(e) {onMessageArrived(e.data)}
    console.log("connected");
    socket.onopen = function() {socket.send("1")};
}

// 收到服务端推送消息的处理逻辑
function onMessageArrived(message) {
    console.log("onMessageArrived: " + message);
    
    var obj = JSON.parse(message);
    
    document.getElementById("image1").src = "myimage/" + obj.L + "_DL.png";
    document.getElementById("image2").src = "myimage/" + obj.M + obj.F + obj.S + "_" + obj.Z48_70 + "_M.png";
    document.getElementById("image3").src = "myimage/" + obj.V + obj.V + "_X";
}

已尝试的无效调整方案

  • 调整方向1:将原WebSocket连接地址ws://mywebsite.com:1880/ws/test改为指向网页容器暴露端口的ws://mywebsite.com:6100/ws/test,因站点已启用HTTPS,触发浏览器安全策略拦截明文ws连接请求
  • 调整方向2:改为直连网页容器内网IP的ws://192.170.0.6:6100/ws/test,跨网段访问限制导致TCP连接无法建立
  • 调整方向3:改为走Nginx反向代理路径的连接地址new WebSocket("ws://mywebsite/webpage/ws/test"),由Nginx规则匹配转发到网页容器对应IP端口,依然无法正常接收WebSocket推送数据

故障根因与修复方案

  1. 补全Nginx反向代理的WebSocket协议支持配置
    普通HTTP反向代理默认无法完成WebSocket的握手升级流程,需要在Nginx站点配置中,对应WebSocket路径的location块下追加协议升级参数:

    location /ws/test {
        # 转发目标指向Node-RED容器的映射端口,不要错误代理到静态网页容器
        proxy_pass http://127.0.0.1:1880;
        proxy_http_version 1.1;
        # 核心配置:传递WebSocket升级请求头
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        # 延长长连接超时时间,避免WebSocket被主动断开
        proxy_read_timeout 86400;
        proxy_send_timeout 86400;
        # 传递基础请求头信息
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
    

    之前第三次调整失败的核心原因,是错误将WebSocket路径的转发目标指向了静态网页容器,而WebSocket的数据源是Node-RED服务,路径匹配规则需要对应到Node-RED的实际服务地址

  2. 修正前端WebSocket连接的协议判断逻辑
    由于站点已启用HTTPS,浏览器会拦截从HTTPS页面发起的明文ws连接请求,需要根据当前页面的访问协议自动匹配WebSocket连接协议:

    function startConnect() {
        document.getElementById('dt').click();
        // 根据页面协议自动选择wss/ws连接,避免HTTPS下的安全拦截
        const wsScheme = window.location.protocol === 'https:' ? 'wss' : 'ws';
        socket = new WebSocket(`${wsScheme}://mywebsite.com/ws/test`);
        socket.onmessage = function(e) {onMessageArrived(e.data)}
        console.log("connected");
        socket.onopen = function() {socket.send("1")};
    }
    

    调整后无需将1880、6100等非标准端口暴露到公网,所有流量统一通过443端口走Nginx反向代理,完全符合浏览器安全策略要求。

  3. 校验Docker容器网络连通性

    • 确认Node-RED容器的WebSocket节点监听地址为0.0.0.0,而非容器内部的127.0.0.1,否则宿主机侧的Nginx无法访问容器内的WebSocket服务
    • 确认Docker Compose的端口映射规则正常:Node-RED容器的1880端口已正确映射到宿主机对应端口,能够被宿主机的Nginx进程正常访问

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.05 01:06:04