web sockets支持本地nginx和npm run dev,但不支持docker compose

vmjh9lq9  于 5个月前  发布在  Nginx
关注(0)|答案(1)|浏览(73)

我有一个react前端和nodejs后端,使用nginx进行服务和负载均衡。当我在本地运行nginx和npm运行dev时,我的设置工作正常,但当我通过docker compose通过docker容器运行时,web sockets无法连接。在控制台中:

websocket.js:43 WebSocket connection to 'ws://localhost/socket.io/?userId=6500d7f273ec607346da303c&EIO=4&transport=websocket' failed:

字符串
我不知所措,我已经试过了所有我能找到的。这是我的设置。

docker-compose.yml

services:
  ws1:
    image: bark-mate-be
    environment:
      - APPID=1111
      - APPPORT=8081
    networks:
      - loadbalancing
    ports:
      - "8081:8080"
  ws2:
    image: bark-mate-be
    environment:
      - APPID=2222
      - APPPORT=8082
    ports:
      - "8082:8080"
    networks:
      - loadbalancing
  ws3:
    image: bark-mate-be
    environment:
      - APPID=3333
      - APPPORT=8083
    ports:
      - "8083:8080"
    networks:
      - loadbalancing
  barkmatefrontend:
    image: bark-mate-fe
    ports:
      - "3000:80"
    networks:
      - loadbalancing
    depends_on:
      - db
      - ws1
      - ws2
      - ws3
  db:
    volumes:
      - barkMate_db:/data/db
    image: mongo:latest
    ports:
      - "27017:27017"
volumes:
  barkMate_db:
networks:
  loadbalancing:

  • nginx.conf*
map $http_upgrade $connection_upgrade {
        default upgrade;
        '' close;
    }

upstream loadbalancer {
    # ip_hash;
    hash $remote_addr consistent;
    server ws1:8081;
    server ws2:8082;
}

server {
        listen 80;
        listen [::]:80;
        server_name localhost;

        location /socket.io/ {
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $host;
            proxy_pass http://loadbalancer;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade"; 
        }

        location /api/ {
            proxy_pass http://loadbalancer;
            proxy_buffering on;  
        }

         location / {
            root   /usr/share/nginx/html;
            index  index.html index.htm;
            try_files $uri $uri/ /index.html;        
        }

}

  • socketio.js*
import { io } from "socket.io-client";
const user = JSON.parse(localStorage.getItem("user"));

export let socket = io("http://localhost:80", {
  path: "/socket.io/",
  auth: { token: "token" },
  query: { userId: user ? JSON.parse(localStorage.getItem("user"))._id : "" },
  autoConnect: false,
  transports: ["websocket"],
  withCredentials: true,
});

socket.onAnyOutgoing((e, m) => {
   console.log("any out going", e, m);
});

socket.on("connect", () => {
   console.log("socket has connected");
  socket.emit("message", {
    type: "test",
    content: {
      msg: "test message",
      userId: JSON.parse(localStorage.getItem("user"))._id,
    },
  });
});

socket.on("message", (msg) => {
   console.log("client recieved the message", msg);
});

socket.io.on("reconnect", (attempt) => {
   console.log("socket reconnection success");
});

Dockerfile //client

FROM node:current-alpine as build
WORKDIR /app
COPY package*.json /app/
RUN npm install
RUN npm ci --production
COPY . .
RUN npm run build

FROM nginx:stable
COPY --from=build /app/build/ /usr/share/nginx/html
COPY nginx/nginx.conf /etc/nginx/conf.d/default.conf

wtzytmuj

wtzytmuj1#

最后,我通过在套接字初始化中省略url来让它工作,如下所示:
在 * socketio.js * 中

export let socket = io({
  path: "/socket.io/",
  auth: { token: "token" },
  query: { userId: user ? JSON.parse(localStorage.getItem("user"))._id : "" },
  autoConnect: false,
  transports: ["websocket"],
  withCredentials: true,
});

字符串
到目前为止,我不确定为什么我不能像在开发中那样点击url,即将其指向nginx服务器。我的想法是它不能点击localhost,因为它应该由它的服务名称引用,所以我必须用不同的url点击nginx图像,我只是不确定那会是什么,因为它是在前端Dockerfile中作为多阶段构建而构建的,而不是在Docker中列为服务-compose. yml。是否将套接字URL指向前端图像服务名称?听起来不对...或者我可以单独构建nginx和前端,并将nginx作为docker-compose.yml中的服务列出,并在该服务名称处访问它,但我认为在前端映像中的多阶段构建是最佳实践。任何见解都将受到赞赏,谢谢。
--编辑
进一步考虑,我相信来自我的react应用程序的请求在前端图像构建期间被设置为命中nginx,并且nginx.conf的服务器指令中的位置块拾取套接字连接的路径,所以这就是为什么我可以将url留空,只添加路径。

相关问题