I run node app like this:
node -r dotenv/config dist/app
I need something similar using PM2:
pm2 start -r dotenv/config dist/app.js --name appname // doesn't work
I receive the next error: error: unknown option -r
Using node_args.
pm2 start --node-args="-r dotenv/config" dist/app.js --name appname
I have made a Shell script:
// pm2-start.sh
NODE_ENV=production &&
node -r dotenv/config dist/app
Then I ran pm2 start pm2-start.sh --name appname
Tip I have also ran: pm2 startup then copied command that pm2 instructed to run in order to activate the auto startup of all apps that are registered via pm2.
Then I ran pm2 save to save the auto service.
Note: pm2 lists apps distinctly between server account respectively. That means that apps that are listed on user A will not be listed on user B. That's true for the pm2 startup command - that should be done for each account.
Hope it helps.
None of this worked for me because I was using an ecosystem file AND cluster mode which behaves really odd (not like without cluster mode...).
I installed dotenv as dev dependency at the root (I was using yarn workspaces too).
Then I did this:
require('dotenv').config({ path: 'path/to/your/.env' })
module.exports = {
apps: [
{
name: 'app',
script: 'server/dist/index.js',
instances: 2,
exec_mode: 'cluster',
instance_var: 'APP_INSTANCE_SEQ',
// listen_timeout: 10000,
// restart_delay: 10000,
}
]
}
Related
Attempting to add clustering ability via PM2 and deploy via my Node/Express application.
I've set up the following command:
pm2 start build/server/app.js -i max
The above works fine locally. I'm testing the functionality on a staging environment on Heroku via Performance 1X.
The above shows the log for the command but attempting 1 instance rather than max. It shows typical info after successfully running pm2 start however you can see app immediately crashes afterward.
Any advice or guidance is appreciated.
I ended up using the following documentation: https://pm2.keymetrics.io/docs/integrations/heroku/
Using a ecosystem.config.js with the following:
module.exports = {
apps : [
{
name: `app-name`,
script: 'build/server/app.js',
instances: "max",
exec_mode: "cluster",
env: {
NODE_ENV: "localhost"
},
env_development: {
NODE_ENV: process.env.NODE_ENV
},
env_staging: {
NODE_ENV: process.env.NODE_ENV
},
env_production: {
NODE_ENV: process.env.NODE_ENV
}
}
],
};
Then the following package.json script handles the deployment per the environment I am looking to deploy e.g. production:
"deploy:cluster:prod": "pm2-runtime start ecosystem.config.js --env production --deep-monitoring",
I got the same error but I fixed it by adding
{
"preinstall":"npm I -g pm2",
"start":"pm2-runtime start build/server/app.js -i 1"
}
To my package.json file
This is advised for production environment
But running
pm2 start build/server/app.js -i max
Is for development purpose
I have a Node app which consists of three separate Node servers, each run by pm2 start. I use concurrently to run the three servers, as a start-all script in package.json:
"scripts": {
...
"start-all": "concurrently \" pm2 start ./dist/foo.js \" \"pm2 start ./dist/bar.js \" \"pm2 start ./dist/baz.js\"",
"stop-all": "pm2 stop all",
"reload-all": "pm2 reload all",
...
}
This all runs fine when running from the command line on localhost, but when I run it as a docker-compose command - or as a RUN command in my Dockerfile - only one of the server scripts (a random one each time I try it!) will launch, but then immediately exit. In my --verbose docker-compose output I can see the pm2 panel (listing name, version, mode, pid, etc.), but then this error message:
pm2 start ./dist/foo.js exited with code 0.
N.B: This is all with Docker running locally (on a Mac Mini with 16GB of RAM), not on a remote server.
If I docker exec -it <container_name> /bin/bash into the container and the run npm run start-all manually from the top level of the src directory (which I COPY over in my Dockerfile) everything works. Here is my Dockerfile:
FROM node:latest
# Create the workdir
RUN mkdir /myapp
WORKDIR /myapp
# Install packages
COPY package*.json ./
RUN npm install
# Install pm2 and concurrently globally.
RUN npm install -g pm2
RUN npm install -g concurrently
# Copy source code to the container
COPY . ./
In my docker-compose file I simply list npm run start-all as a command for the Node service. But it makes no difference if I add it to the Dockerfile like this:
RUN npm run start-all
What could possibly be going on? The pm2 logs show report nothing other than that the app has started.
the first reason is pm2 start app.js start the application in background so that is why your container stops as soon as it runs pm2 start.
You need to start an application with pm2_runtime, it starts an application in the foreground. also you do not need concurrently, pm2 process.yml will do this job.
Docker Integration
Using Containers? We got your back. Start today using pm2-runtime, a
perfect companion to get the most out of Node.js in production
environment.
The goal of pm2-runtime is to wrap your applications into a proper
Node.js production environment. It solves major issues when running
Node.js applications inside a container like:
Second Process Fallback for High Application Reliability Process Flow
Control Automatic Application Monitoring to keep it always sane and
high performing Automatic Source Map Discovery and Resolving Support
docker-pm2-nodejs
The second important thing, you should put all your application in pm2 config file, as docker can only run the process from CMD.
Ecosystem File
PM2 empowers your process management workflow. It allows you to
fine-tune the behavior, options, environment variables, logs files of
each application via a process file. It’s particularly useful for
micro-service based applications.
pm2 config application-declaration
Create file process.yml
apps:
- script : ./dist/bar.js
name : 'bar'
- script : ./dist/foo.js
name : 'worker'
env :
NODE_ENV: development
then add CMD in Dockerfile
CMD ["pm2-runtime", "process.yml"]
remove command from docker-compose.
Docker and pm2 provide overlapping functionality: both have the ability to restart processes and manage logs, for example. In Docker it's generally considered a best practice to only run one process inside a container, and if you do that, you don't necessarily need pm2. what is the point of using pm2 and docker together?
discusses this in more detail.
When you run your image you can specify the command to run, and you can start multiple containers off of the same image. Given the Dockerfile you show initially you can launch these as
docker run --name foo myimage node ./dist/foo.js
docker run --name bar myimage node ./dist/bar.js
docker run --name baz myimage node ./dist/baz.js
This will let you do things like restart only one of the containers when its code changes while leaving the rest untouched.
You hint at Docker Compose; its command: directive sets the same property.
version: '3'
services:
foo:
build: .
command: node ./dist/foo.js
bar:
build: .
command: node ./dist/bar.js
baz:
build: .
command: node ./dist/baz.js
I don't know if my question is stupid but, after hours crushing my brain on it, I prefer to ask you.
I'm trying to run NPM on a Docker container (windows).
I don't want a real "node server" ; I just use NPM to run utilities like gulp, webpack, browserify, vue.js...
So I added this in my ./docker-compose.yml file :
services:
node:
build: docker/node
environment:
- NODE_ENV=dev
Until here, everything sounds good in my head.
Now here is the content of my ./docker/node/Dockerfile :
# See https://github.com/nodejs/docker-node#dockerfile
FROM node:6
EXPOSE 8080
USER node
# set the working directory
RUN mkdir /home/node/app
WORKDIR /home/node/app
# delete existing modules and re-install dependencies
COPY package.json /home/node/app/package.json
RUN rm -rf node_modules
RUN npm install
# launch the app
# EDIT : I removed this line to solve the issue. See answer.
CMD ["npm", "start"]
To create it, I just followed official tutorials.
And then, here is my ./docker/node/package.json file :
{
"name": "custom-symfony-project",
"version": "1.0.0",
"dependencies": {
"gulp": "^4.0.0"
},
"devDependencies": {
"gulp": "^4.0.0"
}
}
I also have 3 containers : PHP, MySQL and NGINX but they are independants and they all start correctly, so I don't thing they are the pain of the issue.
So I run my docker-compose build : everything works fine.
But when I run docker-compose start I got thing in my Node container logs :
npm ERR! missing script: start
I tried to add an empty server.js but the container doesn't start.
So my question is : do I really need to start something ? Do I need a server.js ? I don't what to put into it.
When I was using npm with Ubuntu, I've just never specified a start script..!
Thanks !
Containers are designed to run as long as the process they support is running and a container should run only one process. In your case, you are removing the CMD line, which is starting the process the container supports, so the container has nothing to do and just shuts down immediately.
You should think about your Docker container as a process, not a VM (virtual machine). A VM would have Node and other dependencies loaded and it would be ready to run commands any time you log into it, but a container spins up to run one command and then shut down.
It sounds like you want this container to spin up, run Gulp, then shut down. If that's the case you can use a CMD line like this (assuming you install gulp globally within the Dockerfile):
CMD ['gulp']
Or maybe you want it to spin up and watch for changes using gulp-watch? In that case, the CMD should be something like this:
CMD ['gulp', 'watch']
If you go with either option, note that Gulp will build the files within the container and not on your host filesystem unless you use a bind mount. A bind mount will allow your host filesystem to share a directory with the container and facilitate one or two-way updates to files.
Ok so I remove the CMD line into the Dockerfile but the container just stopped naturally.
So I added the tty: true option into the docker-compose.yml file in order to keep the container active even if nothing's currently running on it, and for the moment it seems to work :
node:
build: docker/node
environment:
- NODE_ENV=dev
container_name: symfony4-windock-node
tty: true
I am trying to start a node program using pm2 via ansible. The problem is that the pm2 start command is not idempotent under ansible. It gives error when run again.
This is my ansible play
- name: start the application
become_user: ubuntu
command: pm2 start app.js -i max
tags:
- app
Now if i run this the first time then it runs properly but when i run this again then i get the error telling me that the script is already running.
What would be the correct way to get around this error and handle pm2 properly via ansible.
Before starting the script you should delete previous, like this:
- name: delete existing pm2 processes if running
command: "pm2 delete {{ server_id }}"
ignore_errors: True
become: yes
become_user: rw_user
- name: start pm2 process
command: 'pm2 start -x -i 4 --name "{{server_id}}" server.js'
become: yes
become_user: rw_user
environment:
NODE_ENV: "{{server_env}}"
I would use
pm2 reload app.js -i max
It will allow you to reload configuration ;-)
I ended up on this page looking for a solution to start PM2 multiple times when I rerun my playbook. I also wanted PM2 to reload the server when it was already running and pickup the new code I might have deployed. It turns out that PM2 has such an interface:
- name: Start/reload server
command: '{{path_to_deployed_pm2}} startOrReload pm2.ecosystem.config.js'
The startOrReload command requires a so-called "ecosystem" file to be present. See the documentation for more details: Ecosystem File.
This is a minimal pm2.ecosystem.config.js that is working for me:
module.exports = {
apps : [{
script: 'app.js',
name: "My app"
}],
};
Here we can use the "register" module to perform a conditional restart/start.
register the output of following command:
shell: pm2 list | grep <app_name> | awk '{print $2}'
register: APP_STATUS
become: yes
and the use APP_STATUS.stdout to make a conditional start and restart tasks. This way we don't need a pm2 delete step.
I have a docker container which uses pm2 to run node like so:
#process.yml
apps:
- script: ./index.js
name: client
watch: true
args: --inspect
#Dockerfile
CMD pm2-docker process.yml
As I could read in that post: The node inspector has arrived in the core of node.js and running a script like so:
node --inspect <somescript.js>
gives some output on the commandline like that: chrome-devtools://… and navigating to that url in chrome, will fire up node-inspector.
How can I do that for a node instance that lives inside a container, but should be debugged from the host.
UPDATE
I could manage to start the debug process by changing two things:
node_args: --inspect=localhost:9080
docker run ... -p 9080:9080
But that brings up one Problem: The URL to use is displayed on the commandline right after node --inspect=... ... is executed, but when running the docker container that information goes down to the logs somewhere. So how can I access the url from there?
You simply publish the required with -p 9229:9229 or
ports:
- 9229:9229
in the docker-compose, and then start it with pm2 and the --inspect arg or directly with node --inspect index.
The url will then be printed out and you can simply use it in chrome like without docker.
To find that line afterwards you can use
docker-compose logs service-name | grep chrome-devtools
or
docker logs container-id 2>&1 | grep chrome-devtools