Node.js & PM2
How to manage Node.js applications
When you have a Node.js app, you need to manage it on your server.
Unlike PHP app, which just need to have NGINX/Apache configuration, a Node.js app can have two production options : generate static project or launch server. With the first, you compile your project into html, js and css files, and you can host it with a basic NGINX/Apache config like PHP app.
It's easy but if you want to update infos of your app with a back-office via an API, infos won't update on your app because it's static app (you will have to re generate your app each time...). The solution is the second option, host a server, it will update infos of your app if you change it with a back-office. To manage a Node.js app like this, you need a manager to keep live your app and PM2 is here for it.
INFO
In this example, we take a project works Express, an old but still used Node.js framework. You can find it here ewilan-riviere/express-starter.
git clone https://gitlab.com/ewilan-riviere/express-starter.git /var/www/express-starter
Create NGINX configuration
You need to have a domain and NGINX. The configuration of Nginx is light but necessary to allow PM2 to serve it on this domain with reverse proxy.
server {
server_name domain.com;
location / {
include proxy_params;
proxy_pass http://localhost:3000;
}
}
With this config, server_name
is the domain to host project and proxy_pass
have a specific port will be used by PM2 (use one specific port by app like 3000, 3001, 3002...).
sudo nginx -t
If you have this output, everything is fine, otherwise you will have some infos to fix it:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
And reload NGINX to apply changes:
sudo service nginx reload
Install PM2
INFO
You have to install Node.js before PM2, you can find a guide here: Node.js
Use NPM globally:
npm install pm2@latest -g
Ecosystem
PM2 is now available on your server, you can use it on different ways but here, we use ecosystem solution. With this, it's easy to maintain a lot of Node.js app with just JSON. You have just to create ecosystem.config.js
anywhere on your server:
vim ~/ecosystem.config.js
module.exports = {
apps: [
{
name: "express-starter",
script: "npm",
cwd: "/var/www/express-starter",
args: "start",
env: {
PORT: 3000, // same port as in Nginx config
},
},
],
};
name
is PM2 id for this appscript
is the package manager used by PM2 to serve this appcwd
is the absolute path of your projectargs
is the action of script from package.json for classic app andenv
define port for this app (you can't serve multiple app on same port).PORT
is the port used by your app
INFO
start
script is "start": "node app.js"
in example of express-starter app.
In this example, express-starter is a Node.js app with theses scripts into package.json:
{
// ...
"scripts": {
"start": "node app.js",
"dev": "nodemon app.js"
},
// ...
}
Start PM2
Now, you can start your app with PM2:
pm2 start ~/ecosystem.config.js
Save this config to restart automatically apps when server reboot:
pm2 save
And list apps with this command:
pm2 ls
You have to see this output:
┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐
│ id │ name │ mode │ ↺ │ status │ cpu │ memory │
├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤
│ 0 │ express-starter │ fork │ 7 │ online │ 0.3% │ 47.2mb │
└────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘
If everything is fine, your app is online and you can access to it via server_name
define in Nginx config.
Cheatsheet
List apps with status
pm2 ls
Save config
pm2 save
Start ecosystem
pm2 start ~/ecosystem.config.js
Kill all apps
pm2 kill
Start app
pm2 start {id}
Start all apps
pm2 start all
Stop app
pm2 stop {id}
Stop all apps
pm2 stop all