I discovered Process Manager 2 (pm2) which I am using to run my Nodejs applications in production. This post details how I set this up, including Docker image build and docker-compose configuration. PM2 includes load balancing, monitoring and more useful features.
Initialise pm2 in your repository
Running pm2 init
will create a pm2.json
file in the root your repository.
pm2.json
{
"name": "My App",
"script": "src/index.js",
"instances": "1",
"env": {
"NODE_ENV": "development"
},
"env_production" : {
"NODE_ENV": "production"
}
}
Creating the DOckerfile
Dockerfile
FROM keymetrics/pm2:latest-alpine
# Bundle APP files
RUN pm2 install pm2-auto-pull
RUN pm2 install pm2-server-monit
COPY package.json .
# Install app dependencies
ENV NPM_CONFIG_LOGLEVEL warn
RUN npm install --production
COPY src src/
COPY public public/
# COPY node_modules node_modules/
COPY config config/
COPY pm2.json .
# Show current folder structure in logs
RUN ls -al -R
CMD [ "pm2-runtime", "start", "pm2.json", "--env","production" ]
Docker Compose COnfiguration
Since I do not like to rememeber docker run
commands I put all my container configurations into docker-compose files from the get-go.
docker-compose.yml
version: "3"
services:
app:
build: .
ports:
- "3031:3031"
network_mode: "host"
environment:
- NODE_ENV=production
Production Deployment
All you need to do now is clone the repostitory to your production server, paste in the production configuration into /config
and start up the Docker compose stack.
docker-compose up --build -d
Then watch as Docker builds the image, creates the container where pm2 takes over to create Node processes running your application.
pm2 comes with some nice features, including the ability to automatically deploy new versions of your application by pulling from the git repository.
Some handy commands
docker-compose exec app pm2 list
Output
┌─────────────────┬────┬─────────┬──────┬─────┬────────┬─────────┬────────┬─────┬───────────┬──────┬──────────┐ │ App name │ id │ version │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │ ├─────────────────┼────┼─────────┼──────┼─────┼────────┼─────────┼────────┼─────┼───────────┼──────┼──────────┤ │ My Application │ 2 │ N/A │ fork │ 170 │ online │ 2 │ 3h │ 0% │ 89.1 MB │ root │ disabled │ └─────────────────┴────┴─────────┴──────┴─────┴────────┴─────────┴────────┴─────┴───────────┴──────┴──────────┘ Modules ┌──────────────────┬────┬─────────┬─────┬────────┬─────────┬──────┬───────────┬──────┐ │ Module │ id │ version │ pid │ status │ restart │ cpu │ memory │ user │ ├──────────────────┼────┼─────────┼─────┼────────┼─────────┼──────┼───────────┼──────┤ │ pm2-auto-pull │ 0 │ 2.0.1 │ 16 │ online │ 0 │ 0% │ 74.1 MB │ root │ │ pm2-server-monit │ 1 │ 3.0.0 │ 25 │ online │ 0 │ 0.6% │ 75.6 MB │ root │ └──────────────────┴────┴─────────┴─────┴────────┴─────────┴──────┴───────────┴──────┘ Use `pm2 show <id|name>` to get more details about an app
docker-compose exec app pm2 restart all
docker-compose exec app pm2 dash
docker-compose exec app pm2 logs