Pm2: Question: Using PM2 inside a docker container?

Created on 19 Jan 2017  路  8Comments  路  Source: Unitech/pm2

Trying to get a node app running under PM2 inside a Docker container and have been having some trouble.

I threw together a minimal example, and this seems to work just fine, but it leaves me wondering鈥攊f PM2 has involved Docker integrations (like keymetrics/pm2-docker-alpine and pm2-docker), why aren't there more examples of using them?

My colleague pointed me towards the Docker best practice of only using one process per container, but this advice seems to be contradicted by Docker's own guide on using Supervisor.

From Nodesource's Docker article:

In the event an application's process crashes, a mechanism is needed to restart it. Docker introduces a paradigm shift with its best practices: one process per container. Unfortunately tools like pm2 or forever require being inside the container, breaking this rule.
It is recommended that the process is restarted at the container level, rather than from within the container. This has the advantage of requiring a single tool for all containers, regardless of what's running inside. This can be leveraged by an agnostic tool like systemd or upstart.

This only gets more complicated when other threads about supervising node apps, suggest instead using the restart: always option for Docker Compose.

Here's the rough gist of what I'd like to achieve:

  • In __development__ I'd like to mount a local volume and restart the _node process_ when a file changes.
  • In __production__ I'd like the process to restart upon failure and expose a health check endpoint.

Is PM2 the right tool for the job?

Question

Most helpful comment

Thanks @Unitech. Just want to follow up quickly to ask about how this would work in production.

Would you rebuild the container from a new image each time the code changes? Not sure how to keep the reloads at zero-downtime that way (no load balancers involved).

Or would you deploy the code to a mounted volume (outside of the container), then signal for pm2 to restart (something like docker exec "npm install && pm2 reload all")?

All 8 comments

Yes it is,

For development, use pm2-dev in your Dockerfile to restart your app on file change within the Docker container.
For production, use pm2-docker in your Dockerfile to restart your app in case of crash.
To expose a health check endpoint you can use the option --web (doc here)

Thanks @Unitech. Just want to follow up quickly to ask about how this would work in production.

Would you rebuild the container from a new image each time the code changes? Not sure how to keep the reloads at zero-downtime that way (no load balancers involved).

Or would you deploy the code to a mounted volume (outside of the container), then signal for pm2 to restart (something like docker exec "npm install && pm2 reload all")?

+1, I am also wondering what is the correct or best way to deploy a new patch to pm2 container. Is there any online document or guide that could follow?

@danprince two years after this discussion... what's your current way to deploy new code via docker & pm2? I am just trying to figure it out.

@beeplin Here's the rough take:

  1. Using standard node docker image
  2. Install pm2 as dependency
  3. Start docker image with following shell script:
#!/bin/sh
set -e

npm=$PWD/node_modules/.bin

if [ "$ENV" == "production" ]
  then $npm/pm2-docker $PWD/process.prod.yml
  else $npm/pm2-dev start $PWD/process.dev.yml
fi

Been deploying code with AWS ECS which handles the container rotation/restarts for you. Not even totally sure that I need pm2 running inside the container, because I'm pretty sure it restarts itself if the main process goes down.

@danprince Thank you for the quick reply~!

In your original question:

Would you rebuild the container from a new image each time the code changes? Not sure how to keep the reloads at zero-downtime that way (no load balancers involved).

Or would you deploy the code to a mounted volume (outside of the container), then signal for pm2 to restart (something like docker exec "npm install && pm2 reload all")?

So now when using pm2-dev/pm2-docker with docker, are you actually mounting your source code folder as a volume outside of the container, or just pack all the source code into the docker image?

The external volume way is, IMO, good for development, but brings complexity to the production deploy procedure, since you have to find another way (like git) to pull the new source code on your server, and run yarn install, instead of simply pull a brand new version of docker image. I wonder which way is better.

In development I'm mounting the source directory as a volume and letting pm2 watch for changes inside the container.

Before deploying, I build a new docker image that's ready to run, by copying the app source over and running yarn install. Then I push the new image to the container registry and point the running containers to the new image tag.

Yeah that makes sense. Thank you~~!!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lefam picture lefam  路  3Comments

waygee picture waygee  路  4Comments

alexpts picture alexpts  路  3Comments

rangercyh picture rangercyh  路  4Comments

jubairsaidi picture jubairsaidi  路  3Comments