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

Docker+Nginx+Cloudflare部署Mattermost遇WebSocket 400错误求助

问题描述

我在EC2服务器上部署了Web应用,并使用Mattermost Docker容器作为聊天系统,以下是我的Docker Compose配置:

version: '3.9'

services:
  br-db:
    container_name: br-db
    platform: linux/amd64
    image: postgres:15.2-alpine
    ports:
      - "54322:5432"
    restart: always
    env_file: './pgsql/local/.env.local'
    volumes:
      - br-pgsql-data:/var/lib/postgresql/data
    networks:
      - br-net

  br-app:
    container_name: br-app
    build:
      context: ./be
      args:
        - DEV=true
    tty: true
    restart: unless-stopped
    working_dir: /app
    env_file: './be/.env.local'
    ports:
      - "8001:8000"
    environment:
      CONTAINER_ROLE: app
      CONTAINER_ENV: local
    volumes:
      - ./be/source:/app
    depends_on:
      - br-db
    networks:
      - br-net

  br-redis:
    image: redis:6.2-alpine
    container_name: br-redis
    ports:
      - "6379:6379"
    restart: always
    volumes:
      - redisdata:/data
    networks:
      - br-net

  br-celery:
    container_name: br-celery
    build:
      context: ./be
      args:
        - DEV=true
    command: celery -A app worker -l info
    tty: true
    restart: unless-stopped
    working_dir: /app
    env_file: './be/.env.local'
    volumes:
      - ./be/source:/app
    depends_on:
      - br-db
      - br-redis
    networks:
      - br-net

  mattermost:
    platform: linux/amd64
    image: mattermost/mattermost-team-edition:latest
    container_name: mattermost
    ports:
      - "8065:8065"
      - "8067:8067"
    volumes:
      - ./mattermost/local/config:/mattermost/config:rw
    restart: unless-stopped
    depends_on:
      - br-db
      - br-app
    env_file: './mattermost/local/.app.env'
    networks:
      - br-net

  mattermost-db:
    container_name: mattermost-db
    platform: linux/amd64
    image: postgres:15.2-alpine
    ports:
      - "54323:5432"
    restart: always
    env_file: './mattermost/local/.db.env'
    volumes:
      - mattermost-db-data:/var/lib/postgresql/data
    networks:
      - br-net

volumes:
  br-pgsql-data:
  redisdata:
  mattermost-db-data:

networks:
  br-net:
    driver: bridge

以下是名为default.conf.tpl的Nginx配置文件:

server {
    listen 80;

    location / {
        uwsgi_pass br-app:9000;
        include /etc/nginx/uwsgi_params;
        client_max_body_size 50M;
        proxy_read_timeout 300s;
    }

   location ~ /api/v4/websocket$ {
        proxy_set_header Upgrade \$http_upgrade\;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host \$http_host\;
        proxy_set_header X-Real-IP \$remote_addr\;
        proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for\;
        proxy_set_header X-Forwarded-Proto \$scheme\;
        proxy_pass http://mattermost:8065;
   }
}
server {
    listen 443;

    location / {
        uwsgi_pass br-app:9000;
        include /etc/nginx/uwsgi_params;
        client_max_body_size 50M;
        proxy_read_timeout 300s;
    }

   location ~ /api/v4/websocket$ {
        proxy_set_header Upgrade \$http_upgrade\;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host \$http_host\;
        proxy_set_header X-Real-IP \$remote_addr\;
        proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for\;
        proxy_set_header X-Forwarded-Proto \$scheme\;
        proxy_pass http://mattermost:8065;
   }
}

我的域名为domain.com,客户端尝试连接wss://domain.com/api/v4/websocket时,Nginx日志显示来自Mattermost的400错误,Mattermost容器日志内容如下:

{"timestamp":"2023-12-21 15:48:07.082 Z","level":"info","msg":"Starting websocket hubs","caller":"platform/web_hub.go:95","number_of_hubs":4}
{"timestamp":"2023-12-21 15:53:36.287 Z","level":"debug","msg":"websocket.NextReader: closing websocket","caller":"platform/web_conn.go:849","user_id":"","conn_id":"ugc36pt8fir6tr3fphzdxb7u3h","error":"websocket: close 1001 (going away)"}
{"timestamp":"2023-12-21 15:53:36.287 Z","level":"debug","msg":"Received HTTP request","caller":"web/handlers.go:173","method":"GET","url":"/api/v4/websocket","request_id":"jgsx4asum7dqxyb996twxnp7ko","user_id":""}

{"timestamp":"2023-12-21 16:09:06.191 Z","level":"debug","msg":"websocket.NextReader: client side closed socket","caller":"platform/web_conn.go:845","user_id":"dunbpz13m3bd7yi3pa3hbuj3hh","conn_id":"rwuerwmspfyo3e7e7pwkk83dew"}
{"timestamp":"2023-12-21 16:09:06.191 Z","level":"debug","msg":"Received HTTP request","caller":"web/handlers.go:173","method":"GET","url":"/api/v4/websocket","request_id":"jymam8uchtgxzjn4pht8r7zknw","user_id":"dunbpz13m3bd7yi3pa3hbuj3hh"}
{"timestamp":"2023-12-21 16:09:18.097 Z","level":"debug","msg":"websocket.NextReader: client side closed socket","caller":"platform/web_conn.go:845","user_id":"dunbpz13m3bd7yi3pa3hbuj3hh","conn_id":"rwuerwmspfyo3e7e7pwkk83dew"}
{"timestamp":"2023-12-21 16:09:18.097 Z","level":"debug","msg":"Received HTTP request","caller":"web/handlers.go:173","method":"GET","url":"/api/v4/websocket","request_id":"6er9kbyjdty1dxqstu116sob9y","user_id":"dunbpz13m3bd7yi3pa3hbuj3hh"}

另外说明:域名托管在Cloudflare,使用自定义SSL证书。请问问题出在哪里?


问题分析与解决

1. Nginx配置中的转义字符错误

你的Nginx配置里,Upgrade \$http_upgrade\; 和 Host \$http_host\; 中的反斜杠是多余的,这会导致传递给Mattermost的请求头格式错误,触发400 Bad Request。

修正后的WebSocket location配置:

location ~ /api/v4/websocket$ {
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_pass http://mattermost:8065;
    # 增加WebSocket必需的长连接超时配置
    proxy_connect_timeout 7d;
    proxy_send_timeout 7d;
    proxy_read_timeout 7d;
}

2. Mattermost外部访问配置缺失

Mattermost需要明确知道自身的外部访问地址和协议,否则会拒绝WebSocket连接。需要在./mattermost/local/.app.env中添加以下环境变量:

MM_SERVICESETTINGS_SITEURL=https://domain.com
MM_SERVICESETTINGS_ENABLEWEBSOCKETSECURE=true
MM_SERVICESETTINGS_TRUSTEDPROXIES=0.0.0.0/0,::/0
  • SITEURL:指定Mattermost的外部访问地址
  • ENABLEWEBSOCKETSECURE:启用安全WebSocket(wss)支持
  • TRUSTEDPROXIES:信任所有代理请求(适配Cloudflare的IP转发)

3. Nginx 443端口缺少SSL配置

当前443端口配置未指定SSL证书和密钥,会导致HTTPS请求无法正常处理,进而影响wss连接。需补充SSL相关配置:

server {
    listen 443 ssl;
    ssl_certificate /path/to/your/custom-cert.pem;
    ssl_certificate_key /path/to/your/custom-privkey.pem;

    location / {
        uwsgi_pass br-app:9000;
        include /etc/nginx/uwsgi_params;
        client_max_body_size 50M;
        proxy_read_timeout 300s;
    }

   location ~ /api/v4/websocket$ {
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://mattermost:8065;
        proxy_connect_timeout 7d;
        proxy_send_timeout 7d;
        proxy_read_timeout 7d;
   }
}

4. Cloudflare配置检查

  • 确保Cloudflare Network设置中WebSocket选项已开启
  • 确认Cloudflare SSL模式为Full或Full (strict),且EC2上的自定义SSL证书有效
  • 添加缓存规则排除/api/v4/websocket路径,避免WebSocket请求被缓存拦截

5. 容器连通性验证

在EC2服务器上执行以下命令,验证Mattermost容器是否能正常接收请求:

curl http://localhost:8065/api/v4/websocket -i

返回400 Bad Request属于正常情况(缺少WebSocket升级头),如果出现连接超时,需检查容器端口映射或br-net网络的连通性。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 11:55:55