AFTER Docker is installed if you need to add a user
sudo adduser https://eventguyz.com/wp-content/uploads/2024/05/hosang-i-t-python-02.png
Make sure that user you don’t have to keep typing sudo in front of every docker command
sudo usermod -aG docker,sudo https://eventguyz.com/wp-content/uploads/2024/05/hosang-i-t-python-02.png
NOTE: for CentOS or RHEL change docker,sudo to docker,wheel
CREATE Project Folder (this can be named whatever you want)
mkdir docker-nginx-lb-v2
cd docker-nginx-lb-v2
CREATING APP SERVERS TO TEST WITH
CREATE a Server folder inside your project folder
mkdir server
cd server
START a node project (package.json) in this folder by running:
npm init -y
ADD the required files that index.js will need when we create it next. So while still in the server folder run this command:
npm install express
CREATE index.js also in the server folder
vi index.js
const express = require("express")
const os = require('os')
const app = express()
app.get("/", (req,res) => {
//res.send("This is the server's response...")
res.json({ message: 'Ok it works....', hostname: os.hostname()})
})
app.listen(5050,() => {
console.log( `Server on port 5050,I am sending a response ${os.hostname()}`)
})To test it, you can run it with the node index.js command and access it from the localhost:5050 port.
curl http://localhost:5050
This is the serverโs responseโฆ
Now that has been validated that the server works, letโs create dockerfile still in the server folder:
vi Dockerfile
FROM node:19-alpine
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 5050
CMD [ "node", "index.js" ]Since nginx and our virtual servers will run on docker we need to create a common network for them to communicate with each other on.
Here we create a network named loadbalance_net with the following command (you only need to do this once):
docker network create loadbalance_net
Now letโs build and create our 4 virtual servers by running the following commands in order (if you made changes to index.js then rerun this commandโฆ it doesnโt hurt to run it again anyhow):
docker build -t server .
Now run these one by one to spin up the application servers
docker run -p 1010:5050 โname backend_server_1 -d โnetwork loadbalance_net server
docker run -p 2020:5050 โname backend_server_2 -d โnetwork loadbalance_net server
docker run -p 3030:5050 โname backend_server_3 -d โnetwork loadbalance_net server
docker run -p 4040:5050 โname backend_server_4 -d โnetwork loadbalance_net serverNow you can validate you can get to each server
curl http://localhost:1010
curl http://localhost:2020
curl http://localhost:3030
curl http://localhost:4040These ports are the ports opened outside of the docker network, so we can access these virtual servers with these ports from outside of docker. But since our nginx server is also a docker container, we will access our backend servers from 5050 port with their own special names, not from these ports.
NGINX LOADBALANCER section
move up to the root of your project directory
cd ..
verify you are in the right place with pwd command
/home/https://eventguyz.com/wp-content/uploads/2024/05/hosang-i-t-python-02.png/docker-nginx-lb-v2
CREATE nginx folder
mkdir nginx
cd nginx
CREATE nginx.conf file
vi nginx.conf
ROUND ROBIN
This is the simplest and most common type of load balancing, where incoming requests are distributed to servers in a cyclical order. Each server is given an equal chance to process a request, regardless of its current load or performance.
upstream backend {
server backend_server_1:5050;
server backend_server_2:5050;
server backend_server_3:5050;
server backend_server_4:5050;
}
server {
listen 80;
include /etc/nginx/mime.types;
location / {
proxy_pass http://backend/;
}
}ROUND ROBIN – weight
This is a variant of round-robin load balancing, where each server is assigned a weight based on its processing capacity, and requests are distributed accordingly. Servers with higher weights are given a higher proportion of incoming traffic.
upstream backend {
server backend_server_1:5050 weight=2;
server backend_server_2:5050 weight=3;
server backend_server_3:5050 weight=1;
server backend_server_4:5050 weight=4;
}
server {
listen 80;
include /etc/nginx/mime.types;
location / {
proxy_pass http://backend/;
}
}LEAST CONNECTION
In this type of load balancing, incoming requests are sent to the server with the fewest active connections, in order to avoid overloading any one server. This is particularly useful for applications that involve long-lived connections, such as streaming media or gaming.
upstream backend {
least_conn;
server backend_server_1:5050;
server backend_server_2:5050;
server backend_server_3:5050;
server backend_server_4:5050;
}COOKIE PERSISTENCE – Layer 7
This type of load balancing operates at the application layer of the network stack and uses information such as HTTP headers, cookies, and URL paths to distribute traffic across servers. This allows for more intelligent routing based on application-specific criteria, such as session affinity, content-based routing, or SSL offloading.
upstream backend {
server backend_server_1:5050;
server backend_server_2:5050;
server backend_server_3:5050;
server backend_server_4:5050;
sticky cookie srv_id expires=1h domain=.example.com path=/
}
#expires = time Sets the time for which a browser should keep the cookie.
###The special value max will cause the cookie to expire on โ31 Dec 2037 23:55:55 GMTโ.
###If the parameter is not specified, it will cause the cookie to expire at the end of a browser session.
#domain= Defines the domain for which the cookie is set. Parameter value can contain variables (1.11.5).
#path= Defines the path for which the cookie is set.SOURCE IP PERSISTENCE
This method uses the IP address of the client to determine which server to send the request to. The IP address is hashed, and the resulting value is used to select the server. This ensures that requests from the same client are always sent to the same server, which can be useful for maintaining session state or other application-specific requirements.
upstream backend {
ip_hash;
server backend_server_1:5050;
server backend_server_2:5050;
server backend_server_3:5050;
server backend_server_4:5050;
}NGINX LB ADDITIONAL OPTIONS
The following parameters can be defined:
STANDARD OPTIONS (comes with free version)
weight=number
sets the weight of the server, by default, 1.
max_conns=number
limits the maximumย numberย of simultaneous active connections to the proxied server. Default value is zero, meaning there is no limit. If the server group does not reside in theย shared memory, the limitation works per each worker process.
Ifย idle keepaliveย connections, multipleย workers, and theย shared memoryย are enabled, the total number of active and idle connections to the proxied server may exceed theย
max_connsย value.
max_fails=number
sets the number of unsuccessful attempts to communicate with the server that should happen in the duration set by theย fail_timeoutย parameter to consider the server unavailable for a duration also set by theย fail_timeoutย parameter. By default, the number of unsuccessful attempts is set to 1. The zero value disables the accounting of attempts. What is considered an unsuccessful attempt is defined by theย proxy_next_upstream, ย fastcgi_next_upstream,ย uwsgi_next_upstream,ย scgi_next_upstream,ย memcached_next_upstream, andย grpc_next_upstreamย directives.
fail_timeout=timesets
- the time during which the specified number of unsuccessful attempts to communicate with the server should happen to consider the server unavailable;
- and the period of time the server will be considered unavailable.
By default, the parameter is set to 10 seconds.
backup
marks the server as a backup server. It will be passed requests when the primary servers are unavailable.
The parameter cannot be used along with theย hash,ย ip_hash, andย randomย load balancing methods.
down
marks the server as permanently unavailable.
PAID/COMMERCIAL OPTIONS
resolve
monitors changes of the IP addresses that correspond to a domain name of the server, and automatically modifies the upstream configuration without the need of restarting nginx. The server group must reside in theย shared memory.
In order for this parameter to work, theย resolverย directive must be specified in theย httpย block or in the correspondingย upstreamย block.
route=string
sets the server route name.
service=name
enables resolving of DNSย SRVย records and sets the serviceย nameย (1.9.13). In order for this parameter to work, it is necessary to specify theย resolveย parameter for the server and specify a hostname without a port number.
If the service name does not contain a dot (โ.โ), then the RFC-compliant name is constructed and the TCP protocol is added to the service prefix. For example, to look up the _http._tcp.backend.example.com SRV record, it is necessary to specify the directive:
server backend.example.com service=http resolve;
If the service name contains one or more dots, then the name is constructed by joining the service prefix and the server name. For example, to look up the _http._tcp.backend.example.com and server1.backend.example.com SRV records, it is necessary to specify the directives:
server backend.example.com service=_http._tcp resolve;
server example.com service=server1.backend resolve;
Highest-priority SRV records (records with the same lowest-number priority value) are resolved as primary servers, the rest of SRV records are resolved as backup servers. If theย backupย parameter is specified for the server, high-priority SRV records are resolved as backup servers, the rest of SRV records are ignored.
slow_start=time
sets theย timeย during which the server will recover its weight from zero to a nominal value, when unhealthy server becomesย healthy, or when the server becomes available after a period of time it was consideredย unavailable. Default value is zero, i.e. slow start is disabled.
The parameter cannot be used along with theย hash,ย ip_hash, andย randomย load balancing methods.
drain
puts the server into the โdrainingโ mode. In this mode, only requestsย boundย to the server will be proxied to it.
While still under the nginx folder create Dockerfile
vi Dockerfile
FROM nginx:stable-alpine
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]Now we have all the nginx files created, we need to build the Dockerfile
docker build -t nginx_load_balancer .
Letโs get the image we built up by mapping it to port 3000 and including it in the network we created before:
docker run -p 3000:80 โname nginx_server -d โnetwork loadbalance_net nginx_load_balancerAfter this process, there will be 5 containers running. Check it out with docker ps (4 backend app servers and 1 nginxLB)
Now validate the nginx LB is working by running:
curl http://localhost:3000
ROLLBACK or DECOMM
Remove NGINX run the following command
docker remove /nginx_serverStop the test APP (nodejs) Servers (you can use the container id instead of /backend_server_1)
docker stop /backend_server_1
docker stop /backend_server_2
docker stop /backend_server_3
docker stop /backend_server_4Remove test APP (nodejs) Servers run the following command (this is removing them from the loadbalancer network. you created)
docker remove /backend_server_1
docker remove /backend_server_2
docker remove /backend_server_3
docker remove /backend_server_4