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
I finally got it working by starting the WebSocket server on a different path and updating the Nginx conf and client handshake path.
and finally connect to the client with
http://localhost:3000/academic/ws/?EIO=4&transport=websocket
Referring to the nginx documentation please try using the following
nginx.conf
:https://www.nginx.com/blog/websocket-nginx/