How to Deploy Multiple Node.js microservice applications in a single EC2 instance using pm2

When it comes to the deployment of microservices using the cloud, there are so many ways possible. Here, let us see one of the simplest ways to do it using the pm2 process manager with a very minimal configuration from the DevOps perspective. It can also be done by anyone.

5/6/20244 min read

Pre-requisites:

  • AWS Account

  • PuTTY

  • Gitlab (or any other Git repositories)

Steps:

  • Let us use the below sample applications for our example.

https://github.com/Jeyabal-B/simple-nodejs-app

https://gitlab.com/jb-sample-projects/demo-nodejs-app

  • Provision of a t2.micro EC2 server from the AWS console. We can choose the following configurations: ubuntu 20.04, t2 micro, and leave the remaining settings as default. Once the server is up, connect to it through PuTTY.
    (Note: The IP address used here is temporary and the instance will be decommissioned after this article is complete)

  • Now, install the node js dependency with the below commands.

curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash - sudo apt install nodejs

  • Verify the installation by using the below command. We should see the installed node version.

node -v

  • Now, let us create a folder for storing our code.

mkdir services

  • Go inside the folder and then clone the first app from GitHub using HTTPS.

cd services

  • Before cloning the code, you have to choose the way that you are going to clone the code from the repository. Either SSH or HTTPS. The SSH is better because it only requires a one-time configuration, unlike HTTPS which requires us to provide authentication each and every time.
    Since this is a demo project, we don’t have to set up our authentication process.

  • Clone the project using the git clone command followed by the repo URL.

  • Now the application has been cloned in our desired location.

  • Let us install Nginx server to run the applications on our server. Give yes (Y) when it asks for your consent to continue with the installation.

sudo apt install nginx

  • Now, we can see a welcome page if you open the EC2 URL.

  • Even if we run the app, we cannot view the response. We first have to set the reverse proxy to expose the app in the default port 80 instead of the application-specific port 3000.

  • To set the reverse proxy, go to the below folder and edit the default file.

cd /etc/nginx/sites-enabled

  • This will be the content for the default file.

##
# You should look at the following URL's in order to grasp a solid understanding
# of Nginx configuration files in order to fully unleash the power of Nginx.
# https://www.nginx.com/resources/wiki/start/
#
https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/
#
https://wiki.debian.org/Nginx/DirectoryStructure
#
#
In most cases, administrators will remove this file from sites-enabled/ and
# leave it as reference inside of sites-available where it will continue to be
# updated by the nginx packaging team.
#
# This file will automatically load configuration files provided by other
# applications, such as Drupal or Wordpress. These applications will be made
# available underneath a path with that package name, such as /drupal8.
#
# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
### Default server configuration
#
server {
listen 80 default_server;
listen [::]:80 default_server;# SSL configuration
#
# listen 443 ssl default_server;
# listen [::]:443 ssl default_server;
#
# Note: You should disable gzip for SSL traffic.
# See: https://bugs.debian.org/773332
#
#
Read up on ssl_ciphers to ensure a secure configuration.
# See: https://bugs.debian.org/765782
#
#
Self signed certs generated by the ssl-cert package
# Don't use them in a production server!
#
# include snippets/snakeoil.conf;root /var/www/html;# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;server_name ;location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try
files $uri $uri/ =404;
}# pass PHP scripts to FastCGI server
#
#location ~ .php$ {
# include snippets/fastcgi-php.conf;
#
# # With php-fpm (or other unix sockets):
# fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
# # With php-cgi (or other tcp sockets):
# fastcgi_pass 127.0.0.1:9000;
#}# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /.ht {
# deny all;
#}
}# Virtual Host configuration for example.com
#
# You can move that to a different file under sites-available/ and symlink that
# to sites-enabled/ to enable it.
#
#server {
# listen 80;
# listen [::]:80;
#
# server_name example.com;
#
# root /var/www/example.com;
# index index.html;
#
# location / {
# try_files $uri $uri/ =404;
# }
#}

  • Now, let's remove this and replace it with our own content for routing.

  • Enter the details and press Ctrl + O to save it, followed by Ctrl + X to exit.

  • Give this command to test if the syntax is alright.

sudo nginx -t

  • Restart the nginx server for this change to reflect.

sudo systemctl restart nginx

  • Now switch into the project directory and give the below commands to install the dependencies and then run the app in our server.

npm install npm run start

  • Now, we can hit the URL and we will be able to see the response.

  • The app will run as long as the console is open so let us make it run in the background with the help of the pm2. Install it using the below command.

sudo npm i -g pm2

  • Verify the installation by giving this command.

pm2 status

  • Run the app with the below command.

pm2 start app.js --name "first-app"

  • Let’s clone the second app now. Let us try using the gitlab instead of github.

  • Clone my below demo project.

jb-sample-projects / demo-nodejs-app · GitLab

  • We can use the same command for cloning. Gitlab is also very similar to github in many ways.

  • Repeat the steps again for this app and update the reverse proxy for the port 4000.

  • Let us set this second app to run if we hit any other URL than “/first”.

  • Now, both the apps are running.

  • Now, we can hit both the URLs and see what happens.

  • Now, we have set it so that any other URLs other than “/first“ goes to the second app. However, the second app only has the “/second“ URL for now. So, only that will work. If we add any new APIs with different URLs then it should work without any changes to the reverse proxy.

Now, that’s all. We can repeat the process and run another app in a different port. set the reverse proxy based on the URI. Then we can have as many apps as the server can handle.