Run PM2 Docker with specific environment - node.js

I have been trying to pass the environment to my PM2 process so that I can target development or production.
My Dockerfile is the following:
FROM keymetrics/pm2:latest
COPY dist dist/
COPY pm2.json .
CMD ["pm2-runtime", "start", "pm2.json"]
I have the following pm2.json:
{
"name": "my-app",
"script": "dist/server.js",
"instances": "1",
"env": {
"NODE_ENV": "development"
},
"env_production" : {
"NODE_ENV": "production"
}
}
And I couldn't manage to get the environment set properly so when I access process.env.NODE_ENV I always get "none" back.
I have tried changing the CMD to:
CMD ["pm2-runtime", "start", "pm2.json", "--env", "production"] and no joy.
I have also tried to get the environment variable set in the dockerfile like this:
ENV NODE_ENV=production and that's not picked up either.
I have also checked the latest PM2 documentation and swapped the pm2.json with a ecosystem.config.js with pretty much the same structure but that hasn't work either.
What am I missing? I'm sure that has to be something really easy to fix but can't get it to work.
THanks

CMD [ "pm2-runtime", "start", "ecosystem.config.js", "--env=production"] is working for me.

Related

PM2 Cluster Mode - Cannot find module 'dotenv/config'

I am trying to run multiple apps using PM2 in cluster mode with config file given below:
"apps": [
{
"name": "Node APIs",
"script": "./server",
"watch": true,
"node_args": "-r dotenv/config",
"instances": "max",
"exec_mode": "cluster"
},
{
"name": "Node Batch",
"script": "./batch_process",
"watch": true,
"node_args": "-r dotenv/config"
}
]
}
Node APIs process is getting errored in pm2 list while Node Batch Process works fine. When I check ~/.pm2/pm2.logs it says:
Cannot find module 'dotenv/config'
I have installed dotenv module both locally and globally but still showing same error.
Also PM2 cluster mode works fine in my local machine but on AWS EC2 it shows above error. What am I missing?
PM2: v4.4.0
NodeJS: v8.12.0
After ages of looking and experimenting, it seems that it doesn't work in cluster mode, but it does in fork mode. Try running it in fork mode.
Try specifying the full path to your package in node_modules via the node_args parameter, even if you are already specifying it in cwd.
It will work in cluster mode.
{
name: 'app-api',
script: '/full/path/to/app/api.js',
instances: 2,
exec_mode: 'cluster',
cwd: '/full/path/to/app',
node_args: ['-r', '/full/path/to/app/node_modules/dotenv/config'],
}

pm2 start in subdirectory

I have a script in package.json like this. To run with npm I would just do it with npm start.
"scripts": {
"start": "cd build && node main"
}
I am currently trying to setup a pm2 config file for this. I created a ecosystem.json file. Neither of both of the following work with pm2 ecosystem command. What am I doing it wrong?
Note that it work if i manually type cd build && pm2 start main.js in command but this is not something i want.
First configuration:
{
"apps": [{
"name": "my-app",
"cwd": "build",
"script": "main.js"
}]
}
Second configuration
{
"apps": [
{
"name": "my-app",
"script": "npm",
"args" : "start"
}
]
}
In your code, you are giving the path incorrectly.
Use following instructions:
Hit pm2 ecosystem command, this will create a new file by name ecosystem.config.js
Remove all the code from the file and add the following code.
module.exports = {
apps : [
{
name : 'API',
script : 'build/main.js',
}
]
};
Hit pm2 start ecosystem.config.js
Check the logs using pm2 logs, your app will be started.
Hope this helps you.

how to pass custom arguments to app

I'm trying to run node app with pm2 via command line and pass only one argument with it
pm2 start app.js --node-args="41"
pm2 start app.js --env dev --node-args="41"
I tried to run it with developement environment and without it but in both ways it didn't worked.
What is the way to do it?
The pm2 command line option --node-args is for passing arguments to the Node.js V8 engine, not to the program running on that engine.
The correct way to pass arguments to your program is this:
pm2 start app.js -- 41
For dev environment:
pm2 start app.js --env dev -- 41
So basically, anything you add after the last two dashes is accessible through process.argv as an array.
You can define a process file at your project root and pass your env and args like this:
process.json
{
"apps" : [
{
"name" : "app-prod",
"script" : "app.js",
"env": {
"NODE_ENV": "production"
}
},
{
"name" : "app-dev",
"script" : "app.js",
"args" : "41",
"env": {
"NODE_ENV": "development"
}
}
]
}
This definition will allow you to pass command line argument (41) that will only be available in your development version.
Then, if you want to run development version of your app, execute it as follows
pm2 start process.json --only app-dev

pm2 --update-env option seems not working

I launched my node app by using ecosystem.config.js like this.
pm2 start ecosystem.config.js
And my ecosystem.config.js is here.
module.exports = {
/**
* Application configuration section
* http://pm2.keymetrics.io/docs/usage/application-declaration/
*/
apps : [
// First application
{
name : "API",
script : "./app/index.js",
env: {
COMMON_VARIABLE: "true"
},
env_production : {
NODE_ENV: "production"
}
},
],
/**
* Deployment section
* http://pm2.keymetrics.io/docs/usage/deployment/
*/
deploy : {
production : {
user : "node",
host : "212.83.163.1",
ref : "origin/master",
repo : "git#github.com:repo.git",
path : "/var/www/production",
"post-deploy" : "npm install && pm2 startOrRestart ecosystem.json --env production"
},
dev : {
user : "node",
host : "212.83.163.1",
ref : "origin/master",
repo : "git#github.com:repo.git",
path : "/var/www/development",
"post-deploy" : "npm install && pm2 startOrRestart ecosystem.json --env dev",
env : {
NODE_ENV: "dev"
}
}
}
}
Then I tried to change the config file for watching mode on. I read this document so, I added watch: true attribute, then I tried pm2 restart ecosystem.config.js --update-env for applying changed config.
The app is restarted and attribute seems to be changed, because when I try pm2 list the watching is enabled. But my app is not restarted after change my code.
So, I just tried pm2 delete 0, pm2 start ecosystem.config.js then It's working well.
Why does --update-env options not working? What do I do wrong?
The only reliable ways I've found to update a pm2 app config is either pm2 kill to stop the daemon, or pm2 delete <id|name> && pm2 start ecosystem.config.js for an individual app (as #hshan mentioned).
This issue claims it was fixed in 2014, but the comments there, plus the string of other questions/issues I found would seem to indicate otherwise:
https://github.com/Unitech/pm2/issues/528
Update: Ongoing discussion here as well: https://github.com/Unitech/pm2/issues/3192
pm2 restart <pid> --update-env worked for me as suggested in this answer
pm2 restart ecosystem.config.js --env production
I don't need --update-env but I do need to specify the env again on restart
Another option that I found was specifying the var on the cmd line:
MY_VAR=1234 pm2 restart ecosystem.config.js
Interestingly, this keeps it in the previous env, but the cmd line var will overwrite the values you have in your ecosystem.config.js for the same var.
However
MY_VAR=1234 pm2 restart ecosystem.config.js --env production
WILL overwrite the cmd line MY_VAR if you have one defined in your ecosystem for production.
This update error happend when it tried to write to Z:\ drive
However, there is no Z:\ drive in my Windows OS machine
Below helped fix the issue:
1 . Add user environment variable as below:
PM2_HOME=%USERPROFILE%\.pm2
2 . Then kill pm2 daemon once
pm2 kill
Now pm2 update works fine.

chef setup: trying to start node app with PM2

I'm using the nodejs cookbook to install node and PM2 module.
include_recipe "nodejs"
nodejs_npm "pm2"
So far, so good. But when I try to start my node app via PM2 with a process.json file it starts but isn't listed in the PM2 output when I ssh into the machine and run pm2 list ... very irritating.
Am I doing something wrong is it correct to not show up there?
execute "start node app via PM2" do
cwd "/share/app"
command "pm2 startOrRestart process.json"
end
and the process.json looks like this:
{
"apps": [
{
"name": "app",
"script": "src/index.js",
"watch": true,
"ignore_watch": ["[\\/\\\\]\\./", "node_modules"],
"merge_logs": true,
"exec_interpreter": "node",
"env": {
"NODE_ENV": "local",
"port": 8080
}
}
]
}
It's because you started the process.json with another user, then when you ssh and do a pm2 list, it only list your current process users.
To avoid that you have two choices:
Do the pm2 start process.json with the same user
Set the PM2_HOME environment variable so all users will hit the same PM2 instance. Eg PM2_HOME='/etc/.pm2' pm2 start process.json && PM2_HOME='/etc/.pm2' pm2 list

Resources