Tivi
Tivi

Reputation: 496

Socket.io error with NGINX when deploying a MERN app with Docker

I have a MERN app deployed on digitalocean with docker. Backend and frontend seem good but for some reason the Websocket, socket.io connection fails on the deployed application.

error message: enter image description here

I use http-proxy-middleware, my setupProxy.js file: (main-be is the name of container)

const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function (app) {
  app.use(
    '/api',
    createProxyMiddleware({
      target: 'http://main-be:5001',
      changeOrigin: true,
    })
  );
};

frontend/src/utils/axios.js:

import axios from 'axios';
export const baseURL = 'https://example.com';
export default axios.create({ baseURL });

frontend/src/utils/constants.js:

const API_BASE_ORIGIN = 'wss://46.111.119.161';
export { API_BASE_ORIGIN };

...here i tried these but none worked:

const API_BASE_ORIGIN = 'https://example.com';
const API_BASE_ORIGIN = 'ws://46.111.119.161:5001';
const API_BASE_ORIGIN = 'ws://46.111.119.161'; 
const API_BASE_ORIGIN = 'wss://46.111.119.161'; 
const API_BASE_ORIGIN = 'wss://46.111.119.161:5001';

part of socketContext.js:

  //* socket connection
  useEffect(() => {

    const newSocket = socketIo.connect(API_BASE_ORIGIN, {
      transports: ['websocket'],
    });
    setSocket(newSocket);
    if (!newSocket) return;
    newSocket.on('connect', () => {
      console.log(`Hurrah Socket ${newSocket.id} Connected`);
    });
  }, []);

NGINX default.conf config file:

upstream api {
    server main-be:5001;
}

upstream client {
    server main-fe:3000;
}



server {
  listen 80;
  listen [::]:80;
  server_name _;
  return 301 https://$host$request_uri;
}

# main server block
server {
  listen 443 ssl http2 default_server;
  listen [::]:443 ssl http2 default_server;

  server_name _;

  # enable subfolder method reverse proxy confs
  include /config/nginx/proxy-confs/*.subfolder.conf;

  # all ssl related config moved to ssl.conf
  include /config/nginx/ssl.conf;

  client_max_body_size 0;


   
     location / {
        proxy_pass http://client;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }


     location /api {
        proxy_pass http://api;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;

    }
      location /ws/ {
        proxy_pass http://client;
            
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_set_header Host $host;
    }
}

Upvotes: 5

Views: 1190

Answers (2)

Bui Huu Quyet
Bui Huu Quyet

Reputation: 1

I also faced some difficulties in deploying fullstack application using react and nestjs with nginx. Here is my approach:

upstream frontend {
    server frontend:5173;
}

upstream backend {
    server backend:5000;
}
server {
    listen 80;


    location / {
        proxy_pass http://frontend;

    }
    location /api/v1/ {
            proxy_pass http://backend;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
        }

    error_page 500 502 503 504 /50x.html;

    location = /50x.html {
        root /usr/share/nginx/html;
    }

    location /socket.io/ {
        proxy_pass http://backend;
            
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_set_header Host $host;
    }
}

Any requests related to socket io will be routed to the /socket.io/ prefix in the backend, requests that interact with the api will be routed to /api/v1/.

This is the env file in fe:

VITE_API_URL=/api/v1/
VITE_SOCKET_URL=/socket.io/

I used docker container to deploy the entire application, including fe container, be container, nginx container.

Upvotes: 0

Tivi
Tivi

Reputation: 496

Solution:

  • add WDS_SOCKET_PORT=0 to the React frontend .env file. (so it will not add an unnecessary additional port)

  • edit the nginx default.conf config file to this (it's not the whole file):

    location /socket.io {
      proxy_pass http://api;
    
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "Upgrade";
      proxy_set_header Host $host; }
    

setupProxy.js file:

const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function (app) {
  app.use(
    '/api',
    createProxyMiddleware({
      target: 'http://main-be:5001',
      changeOrigin: true,
    })
  );
};

frontend/src/utils/axios.js:

import axios from 'axios';
export const baseURL = 'https://example.com';
export default axios.create({ baseURL });

frontend/src/utils/constants.js:

const API_BASE_ORIGIN = 'https://example.com';
export { API_BASE_ORIGIN };

Upvotes: 3

Related Questions