Create a 3 microservices with Docker JWT,Ngnix proxy and load blanching with node Express and Tsoa

June 16, 2023

Certainly! Here’s an example of creating three microservices using Node.js, Express, TypeScript, Docker, Nginx, JWT for authentication, and Tsoa for controller generation:

  1. Set up the project structure:

Create a directory for your project:

mkdir my-microservices-app
cd my-microservices-app

Create three directories for each microservice:

mkdir login-service
mkdir product-service
mkdir order-service
  1. Set up the Login microservice:

Navigate to the login-service directory:

cd login-service

Initialize a new Node.js project:

npm init -y

Install necessary dependencies:

npm install express typescript ts-node nodemon jsonwebtoken tsoa

Create a Dockerfile for the Login microservice:

FROM node:14-alpine

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 3001

CMD [ "npm", "run", "start" ]

Create a tsconfig.json file:

{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "outDir": "dist",
    "strict": true,
    "esModuleInterop": true
  },
  "include": ["src"]
}

Create a src/controllers/authController.ts file for the Login microservice:

import { Body, Controller, Post, Route, Tags } from 'tsoa';
import jwt from 'jsonwebtoken';

@Route('auth')
@Tags('Authentication')
export class AuthController extends Controller {
  @Post('login')
  public async login(@Body() requestBody: { username: string, password: string }): Promise<{ token: string }> {
    // Replace with your actual login logic
    const { username, password } = requestBody;

    // Perform authentication check
    if (username === 'admin' && password === 'password') {
      // Generate JWT token
      const token = jwt.sign({ username }, 'your-secret-key', { expiresIn: '1h' });

      return { token };
    } else {
      this.setStatus(401);
      return { message: 'Invalid credentials' };
    }
  }
}

Create a src/server.ts file for the Login microservice:

import express from 'express';
import { RegisterRoutes } from './routes';

const app = express();

app.use(express.json());

RegisterRoutes(app);

const port = 3001;
app.listen(port, () => {
  console.log(`Login service running at http://localhost:${port}`);
});
  1. Set up the Product microservice:

Navigate to the product-service directory:

cd ../product-service

Follow the same steps as above to set up the Product microservice, including the Dockerfile, tsconfig.json, and controller files. Make sure to install the required dependencies and update the code accordingly for the Product microservice.

  1. Set up the Order microservice:

Navigate to the order-service directory:

cd ../order-service

Follow the same steps as above to set up the Order microservice, including the Dockerfile, tsconfig.json, and controller files. Make sure to install the required dependencies and update the code accordingly for the Order microservice.

  1. Create an Nginx configuration file:

Create an nginx.conf file in the root directory:

http {
  upstream backend {
    server login-service:3001;
    server product-service:3002;
    server order-service:3003;
  }

  server {
    listen 80;

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

Update the product-service/src/controllers/productController.ts file for the Product microservice:

import { Body, Controller, Get, Post, Route, Tags, Security } from 'tsoa';

@Route('products')
@Tags('Products')
export class ProductController extends Controller {
  @Security('jwt')
  @Get()
  public async getAllProducts(): Promise<string[]> {
    // Replace with your actual logic to fetch products
    const products = ['Product 1', 'Product 2', 'Product 3'];
    return products;
  }

  @Security('jwt')
  @Post()
  public async createProduct(@Body() requestBody: { name: string }): Promise<string> {
    // Replace with your actual logic to create a product
    const { name } = requestBody;
    return `Product "${name}" created successfully`;
  }
}

Update the order-service/src/controllers/orderController.ts file for the Order microservice:

import { Body, Controller, Get, Post, Route, Tags, Security } from 'tsoa';

@Route('orders')
@Tags('Orders')
export class OrderController extends Controller {
  @Security('jwt')
  @Get()
  public async getOrderHistory(): Promise<string[]> {
    // Replace with your actual logic to fetch order history
    const orders = ['Order 1', 'Order 2', 'Order 3'];
    return orders;
  }
}

Now, the @Security('jwt') decorator is added to the getAllProducts() method in the ProductController and the getOrderHistory() method in the OrderController. This indicates that these endpoints require JWT authentication. The JWT authentication middleware will be applied to these endpoints, ensuring that only authenticated requests with valid JWT tokens can access them.

Again, please make sure to configure the JWT authentication middleware in your microservices as per your specific implementation.

Set up the Docker Compose file:

Create a docker-compose.yml file in the root directory:

version: '3'
services:
  login-service:
    build:
      context: ./login-service
      dockerfile: Dockerfile
    ports:
      - '3001:3001'

  product-service:
    build:
      context: ./product-service
      dockerfile: Dockerfile
    ports:
      - '3002:3002'

  order-service:
    build:
      context: ./order-service
      dockerfile: Dockerfile
    ports:
      - '3003:3003'

  nginx:
    image: nginx
    ports:
      - '80:80'
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
  1. Start the microservices and Nginx:

Start the microservices and Nginx using Docker Compose:

docker-compose up

Now, you will have three microservices running on ports 3001, 3002, and 3003 respectively, and Nginx running on port 80, acting as a reverse proxy and load balancer to distribute the requests across the microservices.

Note: Adjust the code and configurations as per your specific requirements for the Login, Product, and Order microservices. Also, make sure to implement the JWT authentication middleware in the other microservices (Product and Order) to validate the JWT token from the Login microservice.

Please note that this is a basic example to demonstrate the setup of microservices with Docker, Nginx, and Tsoa. In a production environment, additional considerations, such as scaling, security, and database connections, should be taken into account.


Written by Manoj Bhardwaj who lives and works in Dharamshala Himachal Pradesh (India). My stackoverflow