- Published on
How to Create a Simple Nginx Web Server?
- Authors
- Name
- Emin Vergil
- @eminvergil
Target Audience
I've aimed this article at people who want to learn about Nginx, Docker, Containers, Node.js.
Learning Objectives
After completing this article, you will know how to do the following:
- Create a simple node.js application
- Create and setup nginx configuration
- Create docker images for node.js and nginx
- Setup
docker-compose.yml
configuration - Use docker compose to start entire application
What is Nginx ?
Nginx is a web server that can also be used as a reverse proxy, load balancer, mail proxy and HTTP cache.
In this article, we will use nginx as a load balancer.
Load balancing
A reverse proxy server can act as a “traffic cop,” sitting in front of your backend servers and distributing client requests across a group of servers in a manner that maximizes speed and capacity utilization while ensuring no one server is overloaded, which can degrade performance. If a server goes down, the load balancer redirects traffic to the remaining online servers.
You can see an example nginx configuration for load balancing below:
#ngnix.conf file
http {
upstream myapp1 {
server srv1.example.com;
server srv2.example.com;
server srv3.example.com;
}
server {
listen 80;
location / {
proxy_pass http://myapp1;
}
}
}
In this example, we are listening port 80 to handle requests. For each request, nginx will route the client to srv1 to srv3. When the load balancing method is not specifically configured, it defaults to round-robin.
You can check the other load balancing methods here.
Docker
Docker is a platform for deploying applications. It works by isolating the application into an image. The image will be run by a container, where it contains the operating system and supporting software. (source)
What is a docker container ?
A Docker container image is a lightweight, standalone, executable package of software that includes everything needed to run an application: code, runtime, system tools, system libraries and settings.
When you containerize an application using docker, you don't have to worry about different environments. So when your application runs on your local machine, once you containerize it using docker it will run on a server too. Because you specify which libraries used, so your local environment and a server environment use the same version of libraries and operating system.
An example for Dockerfile for a node application
FROM node:12
WORKDIR /home/node
COPY . /home/node/
RUN npm install
CMD npm run app
Creating a simple http server in node.js
In this article, we will create a simple demo. We will create a HTTP web server using HTTP library.
Here is the implementation for HTTP web server in node.js:
const http = require('http')
const defaultPort = 999
const portNumber = process.argv[2] || defaultPort
const httpServer = http.createServer((req, res) => {
res.statusCode = 200
res.end('this is port: ' + portNumber)
})
httpServer.listen(portNumber, '0.0.0.0', () => {
console.log('listening on port ', portNumber)
console.log(httpServer.address())
})
After this implementation, we will start two web servers with different ports. You can see the example command line below:
node index.js 2222 #this will create a web server on port 2222
node index.js 3333 #this will create a web server on port 3333
After starting two web servers, we can test it using web browser or using curl. You can use curl to make a request to a web server. We can see the get request in the example below:
curl -v localhost:2222 #make a get request on localhost:2222
Response:
* Trying ::1...
* TCP_NODELAY set
* Connection failed
* connect to ::1 port 2222 failed: Connection refused
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 2222 (#0)
> GET / HTTP/1.1
> Host: localhost:2222
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Sat, 09 Jul 2022 15:15:47 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
< Content-Length: 18
<
* Connection #0 to host localhost left intact
this is port: 2222* Closing connection 0
Nginx configuration
In this demo, we will use nginx as a load balancer to route between two web servers.
Here is the implementation:
# nginx.conf file
http
{
upstream all
{
server 192.168.1.36:3333;
server 192.168.1.36:2222;
}
server
{
listen 8080;
location /
{
proxy_pass http://all;
}
}
}
events
{
}
Dockerfile:
FROM nginx
COPY nginx.conf /etc/nginx/nginx.conf
We have to build this image to use it in docker compose. You can build a docker image using build
command. Here is an example
docker build -t nginxapp .
After creating nginx image we can configure the dockore-compose file.
Here is the implementation for docker-compose.yml
version: '3'
services:
nginxapp1:
image: nginxapp
ports:
- '8080:8080'
You can start the application using docker compose up
and kill and remove the containers using docker compose down
.
After starting the nginx application using docker compose up
. You will see the example output in the terminal:
node-nginx-docker-tut-lb-1 | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
node-nginx-docker-tut-lb-1 | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
node-nginx-docker-tut-lb-1 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
node-nginx-docker-tut-lb-1 | 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
node-nginx-docker-tut-lb-1 | 10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
node-nginx-docker-tut-lb-1 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
node-nginx-docker-tut-lb-1 | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
node-nginx-docker-tut-lb-1 | /docker-entrypoint.sh: Configuration complete; ready for start up
This means we started the nginx server, so now we can test it using curl.
❯ curl localhost:8080
this is port: 3333%
❯ curl localhost:8080
this is port: 2222
You can see in this example output when we make a request to the localhost:8080
each request goes to the different HTTP web server using round-robin algorithm.