Deploying an Nodejs Express application to Elastic Beanstalk with PM2 | 2020
There are so many article that shows how to deploy an nodejs on beanstalk but most of them doesn’t works in 2020 and half of them don’t support expressjs. In this article I will explain you how you can deploy your nodejs express application to Elastic Beanstalk with pm2
Prerequisites
- Already have a Node.js express application working locally
- Knowledge on how to create Beanstalk application
- An AWS account
- Less than 15 min of your time
Step 1 : Launch a Beanstalk application. This is straight forward and I wouldn’t be spending much time on this.
Step 2 : Installing pm2 and and init with ecosystem
pm2 init
this will create Generate an ecosystem.config.js
template and replace accordingly
module.exports = {
apps: [
{
name: "name of your project",// <===== edit accordingly
append_env_to_name: true, // <===== add this line
script: "./bin/www.js", // path needs to be relative from ecosystem.config.js
env: {
NODE_ENV: 'development',
},
env_staging: {
NODE_ENV: 'staging',
},
env_production: {
NODE_ENV: 'production',
},
}
]
};
Step 3 : Update package.json for start script
{
"scripts": {
"start": "pm2 start ecosystem.config.js --env environment",
}
Step 4 : Create Procfile
For some reasons and i confirmed with AWS support that npm start doesn’t work out of box on ami linux 2 and so alternative was to use Procfile
web: npm start
NOTE: P is caps in Procfile
Step 5 : create ebextensions
We will be creating 2 files
File 1 : install_pm2.config to install pm2 globally
packages:
yum:
git: []
files:
"/opt/elasticbeanstalk/hooks/appdeploy/pre/03_npm_install.sh":
mode: "000755"
owner: root
group: root
content: |
#!/usr/bin/env bash
EB_APP_STAGING_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k app_staging_dir)
cd $EB_APP_STAGING_DIR
npm install -g pm2
File 2 : renaming env name in package.json in step 3
Reason why I am doing this, In Step 3, We only can define npm start and not anything else. So how do we handle multiple envs
container_commands:
50_rename.config:
command: "/usr/local/bin/settings.sh"
files:
"/usr/local/bin/settings.sh":
mode: "000755"
content : |
#!/bin/bash
# Script to configure package.json file
# Fill variables from environment and parameter store
echo "Filling variables"
environment=$(aws --region $region ssm get-parameter --name "/$stack/$environment/envname" | jq -rc '.Parameter' | jq -rc '.Value')
if (/opt/elasticbeanstalk/bin/get-config container -k app_staging_dir 2>1 ) ; then
app_staging_dir=$(/opt/elasticbeanstalk/bin/get-config container -k app_staging_dir)
app_deploy_dir=$(/opt/elasticbeanstalk/bin/get-config container -k app_deploy_dir)
else
app_staging_dir=$(/opt/elasticbeanstalk/bin/get-config platformconfig -k AppStagingDir)
app_deploy_dir=$(/opt/elasticbeanstalk/bin/get-config platformconfig -k AppDeployDir)
fi
conffile="/package.json"
echo "Filling $conffile with the correct values."
sed -i 's/environment/'$environment'/' $app_staging_dir$conffile
This will fetch env name from parameter store and replace this with env name you define.
That’s it ! deploy your code and we are good.