Load Balancing Node.js Applications with Nginx and Docker Compose

Load Balancing Node.js Applications with Nginx and Docker Compose
docker compose
Nodejs
express
nginx
load balance

Junius L

September 1, 2023

4 min read

Introduction

Node.js has become a popular choice for building scalable web applications due to its non-blocking, event-driven architecture. However, as your application grows and traffic increases, you may face performance bottlenecks. To address this, load balancing becomes crucial. In this tutorial, we'll explore how to load balance a Node.js application using Nginx and Docker Compose.

Prerequisites

  1. Node.js and npm: You can download and install Node.js from the official website (https://nodejs.org/).
  2. Docker and Docker Compose: Install Docker and Docker Compose by following the instructions on the Docker website (https://docs.docker.com/get-docker/).
  3. A basic understanding of Node.js, Nginx, and Docker will be helpful.

Create a Simple Node.js Application

  1. Initialize Project:

    mkdir nodejs-load-balancing
    cd nodejs-load-balancing
  2. Initialize Node.js Project:

    npm init
  3. Install Dependencies:

    npm install express ip
  4. Create the Server File: Create a new file named index.js in the project directory. This will be your main server file where you'll write the code.

  5. Write the Server Code: Open the index.js file in a text editor and paste the following code:

     const express = require('express');
     const IP = require('ip');
     
     const PORT = process.env.PORT || 8080;
     
     const app = express();
     
     app.get('/health', (req, res) => {
       res.send('OK');
     });
     
     app.get('/', (req, res) => {
       res.send(`API is up and running`);
     });
     
     app.listen(PORT, () => console.log(`App is running on http://${IP.address()}:${PORT}`));
     

Dockerize the Node.js Application

Now, let's create a Dockerfile for our Node.js application. In your project directory, create a file named Dockerfile with the following content:

FROM node:16-alpine3.18
 
WORKDIR /app
 
COPY package*.json .
 
COPY yarn.lock .
 
RUN yarn install --frozen-lockfile
 
COPY . .
 
EXPOSE 8088
 
CMD [ "yarn", "start" ]

Create a Docker Compose File

Next, let's create a docker-compose.yml file to define our services and set up Nginx as a load balancer. Here's a sample docker-compose.yml:

version: "3.8"
services:
  api:
    restart: always
    deploy:
      replicas: 2
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "8088-8089:8088"
    environment:
      PORT: 8088
 
  nginx:
    image: nginx:latest
    container_name: reverse_proxy
    depends_on:
      - api
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
    ports:
      - 80:80

In this configuration, we create two instances of our Node.js application using deploy.replicas: 2 and an Nginx load balancer (nginx) that listens on port 80. The depends_on directive ensures that Nginx starts after the Node.js services are up and running.

Configure Nginx

Create an nginx.conf file in your project directory with the following Nginx configuration:

upstream nodejs_servers {
    least_conn;  # Use the least connections load balancing algorithm
    server api:8088;
    server api:8089;
    # Add more server instances as necessary
}
 
server {
    listen 80;
    server_name _;
 
    location / {
        proxy_pass  http://nodejs_servers;
        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;
    }
}

This Nginx configuration defines an upstream block that lists the Node.js application instances and a server block that listens on port 80 and proxies requests to the Node.js instances.

Start the Application

Now, start your application using Docker Compose. Open your terminal and run the following command in your project directory:

docker-compose up

Docker Compose will build the Docker images for your Express.js application and Nginx and then start the services. You can access your load-balanced Express.js application by opening a web browser and navigating to http://localhost.

Conclusion

In this tutorial, we learned how to load balance an Express.js application using Nginx and Docker Compose. Load balancing is essential for improving the performance and scalability of your applications, and Docker Compose simplifies the deployment process. You can further enhance your setup by adding more Express.js instances or configuring Nginx for SSL termination and other advanced features. Happy load balancing!

Source code

https://github.com/julekgwa/nodejs-load-balancing/tree/docker-compose