Deploy a nodejs app to AWS/DigitalOcean like yo do in heroku.
For a while now my deployment workflow has been very simple t
- Prerequisites
Install npm
and pm2
in the production server and make sure they are in the system Path
.
- ssh to your production server
$ ssh user@productionserver
- create deploy directory
$ mkdir my-app
- Navigate inside the deploy directory
$ cd my-app
- Initialise bare repo
$ git init --bare app.git
- Create directory for live code
$ mkdir -p deployments/production # Hold production code
$ mkdir -p deployments/test # Hold test code
- Add post receive git hook
$ touch app.git/hooks/post-receive
$ chmod +x app.git/hooks/post-receive
Inside post-receive
paste the following code snippets
#!/bin/sh
#
## store the arguments given to the script
read prevCommitSHA latestCommitSHA fullbranchName# fullbranchName argument always comes as ref/heads/<branchName>
# and I am only interested with the last namebranch=${fullbranchName##*/}WEBROOT="/home/ubuntu/my-app"
PROJECT="deployments"
APP="myAppName"
LOGFILE="$WEBROOT/$PROJECT/post-receive.log"
DEPLOYDIR=null
PORT=nullecho "log: $LOGFILE"## Record the fact that the push has been received
echo "Received Push Request at $( date +"%F %T" ) for #branch $branch" >> $LOGFILEecho "Checking deployment rules for project:$PROJECT, branch: $branch"# Log the branch name
echo "---------------------------Deploy Start-------------------------------------" >> $LOGFILEif [ $branch = "master" ]
then
DEPLOYDIR="$WEBROOT/$PROJECT/production"
PORT=3000
fiif [ $branch = "develop" ]
then
DEPLOYDIR="$WEBROOT/$PROJECT/test"
PORT=5678
fiif [ $DEPLOYDIR = null ]
then
echo "Received branch $branch, not deploying."
exit
fipm2 stop "${APP}_${branch}" >>null
echo "Stopped server at $( date +"%F %T" )" >> $LOGFILEecho "Deploying to $DEPLOYDIR" >> $LOGFILEecho " - Starting code checkout" >> $LOGFILE
GIT_WORK_TREE="$DEPLOYDIR" git checkout -f "$branch"
echo " - Finished code checkout" >> $LOGFILEecho " - Starting npm install" >> $LOGFILE
cd "$DEPLOYDIR"
rm -rf node_modules
npm install >> $LOGFILE
echo " - Finished npm install" >> $LOGFILEecho "Restarting server using pm2 at $( date +"%F %T" )" >> $LOGFILEPORT="$PORT" pm2 start server.js --name "${APP}_${branch}" >> $LOGFILE
echo "Restart completed at $( date +"%F %T" )" >> $LOGFILE
cd - 1>>/dev/null
echo "---------------------------Deploy Complete---------------------------------" >> $LOGFILEecho "Done. Run 'pm2 ls' on the server to see the process status."
- Update bashrc
As you can see inside the post-receive
hook we have used npm
and pm2
which must be in the PATH
to avoid not-found command
error during push. Despite the fact that you might already have npm and pm2 in the system path but the path environmental variables in linux servers tends to be available only in the interactively shell(e.g when you have login) and since our post receive script will run in non-interactive shell so we will have not-found command
error unless we tweak the system to include environmental variables even in non-interactive shell. To do that update the bashrc
file by commenting out the following lines
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
- Push
Go back to the local server and just push to the production server to see our post-receive
hook in action
$ git push deploy master