skip to Main Content

I’ve been using docker and nginx for my microservice nest js apps with reverse proxy setup for each service so that I can access them under the different paths in the same port.

Dockerfile (identical for each service)

# Use a Node.js LTS version as the base image
FROM node:lts-alpine
# Create a working directory inside the container
WORKDIR /usr/src/app
# Copy the package.json and package-lock.json files to the working directory
COPY package*.json ./
# Install the dependencies
RUN npm install
# Copy the rest of the files to the working directory
COPY . .
# Expose the port 3000 so that the application can be accessed from outside the container
EXPOSE 3000
# Run the application
CMD ["npm", "run", "start:dev"]

nginx.conf

worker_processes 1;

events { worker_connections 1024; }

http {

  upstream users {
    server user-api:3000;
  }

  upstream academic {
    server academic-api:3000;
  }
 
  server {
    listen 80;

    location /users/ {
      proxy_pass http://users/;
    }

    location /academic/ {
      proxy_pass http://academic/;
    }
  }
}

docker-compose.yaml

version: "3"

services:
  academic-api:
    container_name: academic-api
    image: academic-api
    build:
      context: ./academic-api
      dockerfile: Dockerfile.dev
    volumes:
      - ./academic-api:/usr/src/app
      - /usr/src/app/node_modules
    command: npm run start:dev
    restart: unless-stopped

  user-api:
    container_name: user-api
    image: user-api
    build:
      context: ./user-api
      dockerfile: Dockerfile.dev
    volumes:
      - ./user-api:/usr/src/app
      - /usr/src/app/node_modules
    command: npm run start:dev
    restart: unless-stopped

  nginx:
    container_name: nginx
    image: nginx:latest
    ports:
      - "3000:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    depends_on:
      - user-api
      - academic-api
    restart: unless-stopped

I can access my 2 services under http://localhost:3000/academic/ and http://localhost:3000/users/ and everything works fine.

Now I want to add websocket to the academic API and I am using socket io for this. By default the websocket server also starts up on port 3000 which is the http server port as well.

import { OnModuleInit } from "@nestjs/common";
import {
  ConnectedSocket,
  MessageBody,
  SubscribeMessage,
  WebSocketGateway,
  WebSocketServer,
} from "@nestjs/websockets";
import { Server } from "socket.io";

@WebSocketGateway()
export class GatewayService implements OnModuleInit {
  @WebSocketServer()
  server: Server;

  onModuleInit() {
    console.log("GatewayService initialized");
    this.server.on("connection", (socket) => {
      console.log("Socket connected => " + socket.id);
    });
  }
}

But I can’t get this to work on docker environment under nginx proxy. Basically, I want to be able to connect to the websocket if I hit http://localhost:3000/academic/ using websocket protocol using postman.

However, I am able to get this working if I run the academic api server locally on port 3000. When I use http protocol it connects to the http server, and if I use websocket protocol it connects to the websocket server.

2

Answers


  1. Chosen as BEST ANSWER

    I finally got it working by starting the WebSocket server on a different path and updating the Nginx conf and client handshake path.

    @WebSocketGateway({ path: '/ws' })
    export class GatewayService implements OnModuleInit {
    ...
    }
    
    
    server {
        listen 80;
    ...
        location /academic/ {
          proxy_pass http://academic/;
    
          proxy_http_version 1.1;
          proxy_set_header Host $host;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection $connection_upgrade;
        }
    }
    

    and finally connect to the client with http://localhost:3000/academic/ws/?EIO=4&transport=websocket


  2. Referring to the nginx documentation please try using the following nginx.conf:

    worker_processes 1;
    
    events { worker_connections 1024; }
    
    http {
    
      upstream users {
        server user-api:3000;
      }
    
      upstream academic {
        server academic-api:3000;
      }
     
      server {
        listen 80;
    
        location /users/ {
          proxy_pass http://users/;
        }
    
        location /academic/ {
          proxy_pass http://academic/;
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection "Upgrade";
          proxy_set_header Host $host;
        }
      }
    }
    

    https://www.nginx.com/blog/websocket-nginx/

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search