Skip to content
Sandny Blog
  • Home
  • Java
  • JavaScript
  • AWS
  • Embedded
  • About
Docker

Nginx Load Balancer with docker for nodejs services

  • November 3, 2019December 11, 2019
  • by Coder Kai

Nginx Load Balancer with docker has become a fine recipe for managing services in closed systems. Although services like Kubernetes provide container orchestration, sometimes architecturally it could be an overkill. In this example, I will be showing how to use docker services using Nginx load balancer.

Nginx Load Balancer with docker

Request and Response applications

First, create a simple request and response application to test the load balancer. For the request app, I will use a simple http request which prints the load time

const fetch = require('node-fetch');
/**
 * Test HTTP REST
 */
const TEST_ROUNDS = 100;
let httpTimeStarted = Date.now();
const httpTest = () => {
  const promises = [];
  for (i = 0; i < TEST_ROUNDS; i++) { 
    promises.push(fetch('http://localhost:3000/http'));
  }
  return promises;
}

Promise.all(httpTest()).then((data) => {

  data[0].text().then((text) => {
    console.log('\x1b[31m', 'http response data: ', text);
  })

  const nowTime = Date.now();
  console.log('\x1b[0m', '***********************************')
  console.log('\x1b[32m','HTTP Response:');
  console.log('\x1b[0m', 'Total: ', nowTime - httpTimeStarted, 'ms');
  console.log('\x1b[31m','Average: ', (nowTime - httpTimeStarted) / TEST_ROUNDS , 'ms');
  console.log('\x1b[0m');
});

const wsTest = () => {
  for (i = 0; i < TEST_ROUNDS; i++) { 
    ws.send('test');
  }
};

For the response app, I will be using a simple express server. In the following code, there are some other handlers that will connect to websocket and http as well.

import http from 'http';
import express from 'express';
import connectHttp from './ConnectHttpServer';
import connectWebsocket from './ConnectWebsocketServer';
import MongoClient from './MongoClient';
/**
 * Docker configs can be found in docker-compose.yml
 * {localhost}:{APP_PORT}/http endpoint will handle http connections
 * {localhost}:{APP_PORT}/websocket endpoint will handle http connections
 */
// Creates test data in Mongo
MongoClient.CreateTestData();

const APP_PORT = 3001;
const app = express();
const server = http.createServer();

connectHttp(app);
connectWebsocket(app, server);

// connect the app with express
// Serve under the app port
server.listen(APP_PORT, () => {
  console.log(`Request API listening on port ${APP_PORT}!`)
});

The Nginx config and Dockerfiles

The most important part of the service is run by the dockerfile and the nginx config files. The following are the configs of the files.

Add following configs to a nginx.config file to tell  nginx proxy to balance the load between the response APIs. Both Dockerfile and Nginx file can be added to a single folder and so that Docker can find the config file easily.

/ nginx
– Dockerfile
– nginx.config

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {

   upstream nginx {
        server service1:3001;
        server service2:3001;
        server service3:3001;
        server service4:3001;
        server service5:3001;
    }

    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;
    server { 
      location /http {
        proxy_pass http://nginx;
      }

      location /websocket {
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_pass "http://nginx";
      }
    }

    #gzip  on;

    #include /etc/nginx/conf.d/*.conf;
}

Following is the docker file to use it. This is a simple docker file which takes the docker base image for nginx and

FROM nginx:latest

RUN echo "copy content to the response-server docker volume"
COPY nginx.conf /etc/nginx/nginx.conf
RUN ls -a /etc/nginx/

Response server Dockerfile

As my response server is with node.js, I will be using the node base image to install the packages and run the response server. The commands will execute to creaet a mount point as /response-api and install the node modules.

FROM node:8.15.1-jessie
ADD . /response-api
WORKDIR /response-api

RUN echo "copy content to the response-server docker volume"
RUN ls -a

RUN npm install -g yarn
RUN yarn install


This file will contain instructions for Docker to run a node image containing the response server code.

Docker compose file to run the containers

Following is the docker-compose.yml file which will run the containers. Note that the mongo client files have been created for each to show the demo. And also make sure you have good understanding about the names of the container instances that are used as hosts in nginx conf and other request response services.

version: '3'

services:
  # microservices 
  service1:
    environment:
      - service=1
    build:
      context: ../
      dockerfile: ./docker/response-server/Dockerfile
    command: yarn start 
    #volumes:
      #- ../:/response-server
    links:
      - mongo2 

  mongo1:
    hostname: mongo1
    build:
      context: ./mongo
      dockerfile: Dockerfile

  service2:
    environment:
      - service=2
    build:
      context: ../
      dockerfile: ./docker/response-server/Dockerfile
    command: yarn start 
    #volumes:
      #- ../:/response-server
    links:
      - mongo2

  mongo2:
    hostname: mongo2
    build:
      context: ./mongo
      dockerfile: Dockerfile

  service3:
    environment:
      - service=3
    build:
      context: ../
      dockerfile: ./docker/response-server/Dockerfile
    command: yarn start 
    #volumes:
      #- ../:/response-server
    links:
      - mongo3

  mongo3:
    hostname: mongo3
    build:
      context: ./mongo
      dockerfile: Dockerfile


  # nginx dependency 
  nginx:
    build:
      context: ./nginx
      dockerfile: Dockerfile
    hostname: nginx 
    links:
      - service1 
      - service2
      - service3

  requestapi:
    build:
      context: ../
      dockerfile: ./docker/request-api/Dockerfile
    command: npm start 
    ports:
      - "127.0.0.1:3000:3000"
    links:
      - nginx

That’s it. The main parts you should understand and takedown are;

  1.  nginx.conf file
  2. Dockerfile of Nginx and other images
  3. docker-compose.yml file
  4. Names of containers and host port mapping in each of the above containers.

So I hope you got the idea of how it works and will be able to make your own one. Let me know if you have any issues or need any source code.

Create React App Using npx
Java 13 Switch Expressions
Coder Kai
A humble developer
docker express.js javascript lb load balancer nginx

Related articles

Multiple refs for an array of React Elements
Using multiple refs for an…
Immutable and Mutable Values in Javascript
07. Immutable and Mutable Values…
wrapper objects in javascript
06. Wrapper objects in Javascript
globals undefined and null values in javascript
05 Global, null and undefined…
Javascript Booleans and Equality
04. Javascript Guide Booleans and…
How to add Chakra UI Animations
Chakra UI Animations
SSL Websocket using Nginx Proxy
SSL Websocket proxy with Nginx…
Change python version correctly
Python is not setting correct…
optimize React.js load time
How to optimize React.js app…
Multiple refs for an array of React Elements
How to use IntersectionObserver to…
Multiple refs for an array of React Elements
How to dismiss dropdowns when…
Javascript guide Strings
03. Javascript Guide – Strings
How to fetch data with useEffect
How to fetch data with…
add styles to stripe elements
How to add styles to…
Typescript
How to use Typescript with…
how to optimize react-native map view
How to optimize react-native map…
debounce with react hooks
Avoid multiple clicks using debounce…
Numbers inJavascript
02. Javascript Guide – Numbers
Introduction to Javascript
01. Javascript Guide – Introduction…
Create React App Using npx

Categories

  • android 3
  • Apollo Client 1
  • AWS 8
    • AppSync 5
    • EC2 1
    • EKS 1
    • Route53 1
    • S3 1
  • AWS Amplify 1
  • Chakra UI 1
  • Docker 1
  • Embedded 1
  • EmberJS 1
  • FCM 1
  • Godaddy 1
  • GraphQL 3
  • ios 1
  • Jasper 1
  • Java 10
    • Java 11 1
    • Java 14 1
  • JavaEE 2
  • JavaScript 39
    • Express.js 4
    • Javascript Guide 7
    • Node.js 3
    • react-native 4
    • React.js 17
    • Typescript 1
  • Kubernetes 1
  • machine learning 1
  • Maven 2
  • OCaml 3
  • PostgreSQL 1
  • Python 2
  • react-native 4
  • ReactJS 3
  • sass 1
  • Server 6
  • spark 1
  • Terraform 2
  • Ubuntu 4
  • Uncategorized 1
  • webpack 2

Recent Comments

  • Pamela587 on Chakra UI Animations
  • Alicia1760 on Chakra UI Animations
  • vneuweluso on How to add styles to stripe elements without using CardElement

Meta

  • Log in
  • Entries feed
  • Comments feed
  • WordPress.org

Archives

  • October 2022 3
  • September 2022 7
  • May 2022 1
  • December 2021 1
  • August 2021 1
  • July 2021 6
  • June 2021 3
  • February 2021 1
  • July 2020 1
  • December 2019 5
  • November 2019 6
  • October 2019 3
  • August 2019 1
  • March 2019 1
  • February 2019 1
  • January 2019 2
  • December 2018 1
  • September 2018 2
  • August 2018 1
  • June 2018 1
  • February 2018 1
  • November 2017 2
  • October 2017 5
  • September 2017 1
  • June 2017 1
  • May 2017 10
Sandny Blog space
Theme by Colorlib Powered by WordPress