Node PM2 + Nginx + Docker

Simple NodeJs server managed by PM2 for performance optimizations and reversed proxy via nginx. The setup is run in Docker containers. Docker makes it easy to pass env variables to nginx

Node JS Basics

PM2

We can use the Node cluster module to spin up child process and make our code use the multi core cpu, but the management of these child process can get cumbersome, that's why in production its prefered to use PM2. The definition of PM2 from its website

PM2 is a daemon process manager that will help you manage and keep your application online 24/7

PM2 setup

We can configure PM2 either using cli arguments or the config file, and in this repo we have used the config file ecosystem.config to configure our PM2. Here is our basic configuration:

module.exports = { apps: [ { name: "node-be", script: "./server-pm2.js", exec_mode: "cluster", instances: "max", log_type: "json", log_file: "./logs/log.json", out_file: "./logs/out.json", error_file: "./logs/error.json", env: { PORT: 3000, SERVER_NO: "Server 1", }, }, { name: "node-be-2", script: "./server-pm2.js", .... env: { PORT: 3001, SERVER_NO: "Server 2", }, }, ], };

NGINX

Nginx is a web server that can also be used as a reverse proxy, load balancer, mail proxy and HTTP cache. We have used it for reverse proxy and load balancing.

// default.conf.template file server { listen ${NGINX_PORT}; server_name ${NGINX_HOST}; location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_pass http://${SERVER_HOST}:${SERVER_PORT}/; proxy_http_version 1.1; } }
// instead of upstream nodeapi { server localhost:${SERVER_PORT}; server localhost:${SERVER_PORT2}; } // to using local ip upstream nodeapi { server 172.18.0.1:${SERVER_PORT}; server 172.18.0.1:${SERVER_PORT2}; }

Local Development

For local development make sure the following things are setup:

  1. You have Desktop version of Docker installed and running.
  2. Run npm install for installing the dependencies.
  3. There is a default .env file provided feel free to update the values. But make sure the PORT values match the PM2 config.
  4. Then run either of the commands below for starting a docker container
docker composr up --build ---> to re build the image docker compose up --> if image exists docker exec -it nginx-server sh ---> to checks thr logs in docker container. Here `nginx-server` is the name of the container.