A Guide to NGINX Load Balancing for Dockerized Node.js Apps

2024-03-10

Load balance between trucks

Introduction

In this guide we are going to learn how to use NGINX to load balance a Dockerized Node.js application. We will start by creating a simple Node.js application and then we will create a Docker image for it. We will then create a simple NGINX configuration to load balance the application (also we will use Docker for nginx 💪).

prerequisites

You should already know about Docker, nodesjs and nginx

Step 1: Create a simple Node.js application

create a new directory and create a file called app.js and add the following code to it:

 
const express = require("express");
const app = express();
const os = require("os");
const hostname = os.hostname();
app.get("/", (req, res) => res.send("Hello from " + hostname));
app.listen(8080, () => console.log("listening on port 8080 on " + hostname));

Then run this command to initiate npm and install express:

Terminal window
 
npm init -y
npm install express

Step 2: Create a Docker image for the Node.js application

Create a file called Dockerfile in a root directory and add the following code to it:

Terminal window
 
FROM node:20.11.1
WORKDIR /home/node/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 8080
CMD ["node", "app.js"]

step 3: Build the Docker image

Run the following command to build the Docker image:

Terminal window
 
docker build -t node-app .

step 4: Write the NGINX configuration

Create a file called nginx.conf in the root directory and add the following code to it:

Terminal window
 
http {
upstream nodebackend {
# we can point to the conatiner name if we use user-defined bridge network in docker
server nodeapp1:8080;
server nodeapp2:8080;
server nodeapp3:8080;
}
server {
listen 8080;
location / {
proxy_pass http://nodebackend/;
}
}
}
events {
}

You can create create a custom dockerfile for nginx and add the nginx.conf file to it. But for simplicity we will use the default nginx image and mount the nginx.conf file to it via command line.

step 5: Really Important Step

If you look closely at the nginx config file, you will see that we are using the container names as the server names. This is only possible if you use user-defined bridge network .

Here is how you can create a user-defined bridge network:

Terminal window
 
docker network create -d bridge load-balance

-d will specify the driver to use for the network. In this case, we are using the bridge driver. And the name of the network is load-balance .

You can verify that the network has been created by running the following command:

Terminal window
 
docker network ls

step 6: Run 3 Node.js application via Docker

3 instances of the Node.js application will be running on different ports. We will use the --network flag to specify the network to use.

3 is just an example, you can run as many instances as you want.

Terminal window
 
docker run --name nodeapp1 --hostname nodeapp1 -p 2222:8080 --network load-balance -d node-app
docker run --name nodeapp2 --hostname nodeapp2 -p 3333:8080 --network load-balance -d node-app
docker run --name nodeapp3 --hostname nodeapp3 -p 4444:8080 --network load-balance -d node-app

--name is used to specify the name of the container and this flag will help us to use the name of container in nginx.conf file instead of the ip address.

--hostname is used to specify the hostname of the container, if you see the the app.js file we are using os.hostname() to get the hostname of the container. The reason I used this flag is to prove that load balancing is happening when you refresh the page.

At this point you can visit http://localhost:2222 , http://localhost:3333 and http://localhost:4444 and you will see the response from the Node.js application.

port 2222 is running

step 7: Run the NGINX container

Run the following command to run the nginx container:

Terminal window
 
docker run --name nginx --hostname ng1 -p 80:8080 -v ./nginx.conf:/etc/nginx/nginx.conf --network load-balance -d nginx

Now visit http://localhost and you will see the response from the Node.js application. If you refresh the page you will see the response from different containers. This is because the load balancing is happening.

Conclusion

In this guide we learned how to use NGINX to load balance a Dockerized Node.js application. We created a simple Node.js application and then we created a Docker image for it. We then created a simple NGINX configuration to load balance the application. We used Docker for nginx and we used user-defined bridge network to make the containers communicate with each other.