Prelude
While developing apps on NodeJS, you must have used packages like Nodemon, which monitors your code for changes and restarts your Node App. Though Nodemon is super useful in development, it's not recommended to use it in Production. Nodemon is not something you use if you wish to keep your app alive on Production if it crashes.
Here's where PM2 comes in handy. I've been hosting my NodeJS apps using PM2 on production as well I use PM2 for Development.
Quoting from PM2:
PM2 is a production process manager for Node.js applications with a built-in load balancer. It allows you to keep applications alive forever, to reload them without downtime, and to facilitate common system admin tasks.
Before we go ahead and configure the PM2, yes, PM2 does support the auto-reload feature like Nodemon using the watch
feature. More on this later in the article.
Configuring PM2
PM2 simplifies the way you could define the configuration for your app using PM2 ecosystem configuration file. You could use a PM2 configuration file for configuring multiple envs, logging, etc.
Here's a snippet for configuring your PM2 envs and I'll brief each of these later in the article.
ecosystem.config.js
module.exports = {
apps: [
{
name: "PROJECT_NAME",
script: "./server.js",
instances: 2,
max_memory_restart: "300M",
// Logging
out_file: "./out.log",
error_file: "./error.log",
merge_logs: true,
log_date_format: "DD-MM HH:mm:ss Z",
log_type: "json",
// Env Specific Config
env_production: {
NODE_ENV: "production",
PORT: 8080,
exec_mode: "cluster_mode",
},
env_development: {
NODE_ENV: "development",
PORT: 8080,
watch: true,
watch_delay: 3000,
ignore_watch: [
"./node_modules",
"./app/views",
"./public",
"./.DS_Store",
"./package.json",
"./yarn.lock",
"./samples",
"./src"
],
},
},
],
};
You can put the configuration file at the root level of your project.
Basic Configuration
-
name
This could be your project name and PM2 will use this name to name your workers.
-
script
The entry point of your app, mostly it's the
server.js
. Make sure you set the right path, the above configuration assumes that you've theecosystem.config.js
and theserver.js
file at the root level of your project. -
instances
This is the number of workers you wish to spawn.
-
max_memory_restart
PM2 allows you to reload your application based on the memory limit you specify using the
max_memory_restart
.
Logging Configuration
-
out_file
Generic logging, all your
console.log()
statements are logging in this file along with other information. -
error_file
Similar to
out_file
but error files only log the errors of your application. -
merge_logs
This is not needed if you are fine with PM2 storing a unique log file for each of its PID - Process ID). Using this config will merge all your app logs into a single file.
merge_logs
will merge your log files of various PIDs and it doesn't merge the output and error logs into one. -
log_date_format
The above is self-explanatory. You could define a date/time format you wish to print your logs in.
-
log_type
Specify the output style, it's raw by default but we are using JSON here.
Logs Path & Disabling Logs
By default, your Logs are stored under$HOME/.pm2/logs/<app name>-(out||error)-<pid>.log
. You could disable logging by pointing the log path toout_file: "/dev/null"
and the same is applicable forerror_file
Environment specific Configuration
-
env_production && env_development
These are nothing but different environments you wish to run your apps in, using PM2. You could create config for multiple staging env if your setup requires to do so.-
NODE_ENV
The above set the env variable value to Production / Development for your app. -
PORT
Port at which you would like to initiate your app at.
-
-
exec_mode
You could use cluster or fork, where the latter is the default mode. It is recommended to use the cluster mode on production and you could use a single instance locally. Number specified in the instances creates child processes (workers) and distributes the incoming connections across the worker processes. You could set the value to 0 or max to specify how many workers you wish the PM2 should launch (max will spawn as many workers as the number of available cores). From PM2 DocsThe worker processes are spawned using the child_process.fork() method, so that they can communicate with the parent via IPC and pass server handles back and forth.
-
watch
We need to use this only on the dev envs. The use case is exactly what nodemon does. The watch monitors the file changes in your app and restarts your app as soon as a file change is detected. -
watch_delay
You don't want to end up restarting your app as soon as you save your file. So if you try to save your file multiple times in under three seconds, it will only restart your app once as it will clear the watch timer every time you save your files under three seconds. -
ignore_watch
There will your app will end up restarting even if you install an NPM package, add or move a file in your app dir, or as simple as add an img in your public dir. Hence, any folder or file paths added to the ignore_watch array will not trigger a restart of your app as they are not relevant and don't require your app to be restarted in the first place.
Useful PM2 commands
Starting your App in Dev & Production mode
You could add the following commands to package.json
"scripts": {
"start_dev": "pm2 start ecosystem.config.js --env development",
"start_prod": "pm2 start ecosystem.config.js --env production"
},
You could execute the above commands like npm run start_dev
and npm run start_prod
which starts your app in dev and production mode with the given config.
Start, Stop, Restart & Kill your App
Kill your App
pm2 kill #kills all pm2 workers
Reloading your App
pm2 reload all
Restarting your App
pm2 restart all
Alternatively, you could pass the PID instead of using all
keyword which will end up running the same operation on all the processes.
Restarting a process will kill and restart it as opposed to reloading which achieves a 0-second-downtime reload.
Logs
Delete all Logs
pm2 flush
Read Logs
pm2 logs
Processes
List Processes
pm2 list
Monitor Processes
pm2 monit
References
You could also configure the deployment process using the PM2 but I've not covered it in the above tutorial as I've never used it personally.
Here are some resources which will help you understand PM2 configuration in detail.
Top comments (1)
Nice explanation about ecosystem.config.js. I came across one blog similar to yours that is suitable for novice developer in PM2.
jksnu.blogspot.com/2024/10/master-...