Load Balance using Nginx

Let's take the example forward by load balancing the Node.js application.
Checkout the commit
$ cd nginx-and-nodejs-on-docker
$ git checkout 2e3a77e
.env File
The container names are changed:
docker-compose.yml
A new service called node_server_2
is created and the initial server is renamed to node_server_1
.
web/server.js
This is an optional change. x-powered-by
header that defaults to EXPRESS
is disabled, and a new header X-Server
is added to find out which container served the request.
Rebuild & Recreate containers
As usual, rebuild using docker-compose build
followed by docker-compose up -d
. Once the containers are up, you should be able to browse to http://192.168.99.100:81/users
& http://192.168.99.100:82/users
. Check the headers using Chrome inspect tool. Notice the X-Server
header.
Add Nginx for load balancing
Nginx is super light and a great fit for reverse proxy scenarios like this one. If you are unfamiliar with Nginx, you may want to read my book Nginx: From Beginner to Pro. It is extremely simple and straightforward to use it with Docker.
Let's Dive in
Step 1: Change your directory and checkout the commit
$ cd nginx-and-nodejs-on-docker
$ git checkout bd9e91f
OR view the differences online.
Review the following files:
.env
file
It now contains the information about NGINX
# Project Information
COMPOSE_PROJECT_NAME=node-nginx-seed
TAG=1.0
# Database Information
DATABASE_VERSION=mongo:3.4.8
DATABASE_CONTAINER_NAME=mongodb
# NodeJS Information
NODE_VERSION=node:6.11.3
NODE_CONTAINER_NAME_1=node_server_1
NODE_CONTAINER_NAME_2=node_server_2
# Nginx Information
NGINX_VERSION=nginx:1.13.3
NGINX_CONTAINER_NAME=nginx
docker-compose.yml
file
version: '2'
services:
database:
image: ${DATABASE_VERSION}
networks:
- backend
container_name: ${DATABASE_CONTAINER_NAME}
volumes:
- mongo-data:/data/db
- ./docker/scripts:/scripts
- ./docker/data:/data
node_server_1:
environment:
- NODE=${NODE_CONTAINER_NAME_1}
container_name: ${NODE_CONTAINER_NAME_1}
image: ${NODE_VERSION}
build:
context: ./web
dockerfile: node.dockerfile
networks:
- backend
volumes:
- ./web:/web
depends_on:
- database
node_server_2:
environment:
- NODE=${NODE_CONTAINER_NAME_2}
container_name: ${NODE_CONTAINER_NAME_2}
image: ${NODE_VERSION}
build:
context: ./web
dockerfile: node.dockerfile
networks:
- backend
volumes:
- ./web:/web
depends_on:
- database
nginx:
container_name: ${NGINX_CONTAINER_NAME}
image: ${NGINX_VERSION}
build:
context: ./nginx
dockerfile: nginx.dockerfile
networks:
- backend
ports:
- 80:80
depends_on:
- node_server_1
- node_server_2
- database
networks:
backend:
driver: bridge
volumes:
mongo-data:
Notice the following changes:
ports
key has been removed from individualnode
servers. This is to ensure that you can't reach the Node.js application directly. It avoids exposing your application to the end users.depends_on
key is added to imply dependencies between services.docker-compose up
starts services in dependency order.docker-compose up
SERVICE_NAME will automatically include SERVICE’s dependencies.
nginx
service sets the context to thenginx
directory and refers to thenginx.dockerfile
for its image. It is connected to thebackend
network so that it is able to talk to the Node.js apps and maps external port80
to the internal port80
.
nginx.dockerfile
file
FROM nginx:1.13.3
MAINTAINER rahul soni Soni < rahul soni@xxxx.com>
# Copy the Nginx configuration
COPY nginx.conf /etc/nginx/nginx.conf
# Expose website on port
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
To avoid the container being shutdown, you tell Nginx to run as a foreground process and listen to the requests.
Rebuild & Recreate containers
Rebuild again using docker-compose build
followed by docker-compose up -d
. Once the containers are up, you should be able to browse to http://192.168.99.100/users
. Check the headers using Chrome inspect tool. Notice the X-Server
header. You should see it switch values between node_server_1
and node_server_2
if you refresh the page.
What next?
Stay tuned for upcoming articles. You may contact us for your software and consultancy requirements.
© 2025, Attosol Private Ltd. All Rights Reserved.