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
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.