update:
you may not be in favour of using pm2 inside Docker but sometimes the application requirements are different and you may need to run two nodejs application in one docker container, so in case if you want to run frontend and backend application in the same container then in the case pm2 work well then other workarounds.
So now we have pm2-runtime which run the docker process in the foreground, your application will be running the foreground with pm2 and you can expect the same result as running without pm2.
So with pm2-run time
- You can run multiple node application in the Docker container
- You can run the application now in the foreground
- You can integrate with key metrics
- You produce custom metrics
- the same behaviour of the container as without pm2 but with pm2 have some these advantages.
- You can now control the restart behaviour, ( if a process crash the pm2 will do an auto restart, if disabled then the container will be terminated)
- In development environment like in mounting you do not need to restart container but just restart the pm2 processes
pm2 restart all
, which will save time development.
FROM node:alpine
RUN npm install pm2 -g
CMD ["pm2-runtime", "app.js"]
or If you want to run multiple node application in a container then you can process.yml
FROM node:alpine
RUN npm install pm2 -g
CMD ["pm2-runtime", "process.yml"]
process.yml file
You can also create an Ecosystem file in YAML format. Example:
This will allow the container to run multiple nodejs processed.
apps:
- script : ./api.js
name : 'api-app'
instances: 4
exec_mode: cluster
- script : ./worker.js
name : 'worker'
watch : true
env :
NODE_ENV: development
env_production:
NODE_ENV: production
If you want to run with Keymetrics.
Keymetrics.io is a monitoring service built on top of PM2 that allows
to monitor and manage applications easily (logs, restart, exceptions
monitoring…). Once you created a Bucket on Keymetrics you will get a
public and a secret key.
FROM node:alpine
RUN npm install pm2 -g
CMD ["pm2-runtime", "--public", "XXX", "--secret", "YYY", "process.yml"]
Disable Auto restart:
With this flag, the container will be killed if the nodejs process killed or stopped due to an error or exception. Sometimes we do not auto restart the process but we want to restart the container.
FROM node:alpine
RUN npm install pm2 -g
CMD ["pm2-runtime","app.js","--no-autorestart"]
Without pm2 runtime
As a rule of thumb only one process per container. So keeping this in mind you start your process inside the container using node start server.js
as you did without docker. What will happens here if nodejs server crash? your container will be killed in this case. which one should avoid doing this.
Your container will be killed whenever the nodejs server goes down because the primary process will go down and that process should be in the foreground as being the primary process of the container.
So ultimately there is pm2 for that. This is how you can use pm2 and supervisord together to achieve that.
If you are also looking for an example, Here is the dockerfile and required config file. Using the alpine most lightweight image of 2MB.
FROM alpine:3.7
COPY supervisord.conf /etc/supervisord.conf
#installing nodejs and supervisord
RUN apk add --no-cache --repository http://dl-cdn.alpinelinux.org/alpine/v3.7/main/ \
--repository http://dl-cdn.alpinelinux.org/alpine/v3.7/community/ \
sudo supervisor nodejs>=8
RUN npm i pm2 -g
COPY pm2.conf /etc/supervisord.d/pm2.conf
supervisord.conf
[unix_http_server]
file = /tmp/supervisor.sock
chmod = 0777
chown= nobody:nogroup
[supervisord]
logfile = /tmp/supervisord.log
logfile_maxbytes = 50MB
logfile_backups=10
loglevel = info
pidfile = /tmp/supervisord.pid
nodaemon = true
umask = 022
identifier = supervisor
[supervisorctl]
serverurl = unix:///tmp/supervisor.sock
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[include]
files = /etc/supervisord.d/*.conf
pm2.conf
[supervisord]
nodaemon=true
[program:pm2]
command:pm2 start pm2_processes.yml --no-daemon
startretries:5