Building a Node Js Application and deploying through Docker: Express Myself

Nirat Attri
3 min readApr 3, 2017

--

There are plenty of articles that do what the title says. But I found the lessons from them very scattered and the combination I worked on was one which hasn’t been much documented yet. I’ll be describing this as a multipart series where I build the application from scratch and hope to isolate the technologies used in each part, and in the end, I hope to combine it together into one working, basic application. We’ll be using express for our server, the ORM is going to be a knex, bookshelf hybrid (More on this later), front-end beautification will be React and finally we’ll be deploying what we make through docker.

Getting Started

First step would be to install node if you haven’t 😅

https://nodejs.org/en/download/

Node comes with npm pre-installed and we’ll be using it as our default package manager.

Express describes itself as “a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications.” We’ll use the express-generator cli tool to get started with it.

npm install express-generator -g

Now, let’s create a barebones express application called myAwesomeApp.

express --view=pug myAwesomeApp

Install the dependencies:

cd myAwesomeApp && npm install

This step might give the jade rename warning for some mac users where the generated templates might still be jade. Skip the following steps if your views templates were created with a .pug extension.

npm uninstall jade --save
npm install pug --save

Edit your app.js file and replace the line:

app.set(‘view engine’, ‘jade’);

with

app.set(‘view engine’, ‘pug’);

Also,

cd views
for old in *.jade; do mv $old `basename $old .jade`.pug; done

Essentially speaking, your node application is now ready

npm start

Your application is running on localhost:3000 . Yay, you! You’re awesome.

I want to include a little note if you’re using git, include your node_modules in your .gitignore file as a good practice. Not only does it reduce upload size, but in a collaboration, you’ll be saved the headache of some super pointless merge conflicts.

For my mac buddies, add the .DS_Store file too. It’s just annoying to have it there. 😝

A Biased Development Tweak

I’m very biased towards using pm2 for setting up my servers. So, pm2 is a process manager that manages your applications states, so you can start, stop, restart and delete processes. It’s very tightly coupled with docker as we’d see later on. Plus, the watch and hot reload feature make development super easy. I earlier considered having this as a part of a separate article which is production specific but I just couldn’t ignore it’s helpfulness while developing.

First, install pm2 (globally. Thank me later since you’d probably be using it a lot)

npm install -g pm2

To run your application and reload automatically on file changes use

pm2-dev start bin/www

For those familiar with pm2, the above command is an abstraction over the --watch --no-daemon flag combination.

For the sake of application structuring, create a new folder pm2_configs and inside it, create a config.json. The file should look something like this:

{
"apps" : [{
"name" : "myAwesomeApp",
"script" : "./bin/www",
"exec_mode" : "cluster",
"instances" : 1,
"merge_logs" :true,
"env": {
"PORT": 3000,
"MONITORING": false
},
}]
}

Your start command now becomes

pm2-dev start pm2_configs/config.json

A good measure is to include these start methods as part of your package.json so that they can be run through npm. Also, it might be a good idea to assign this awesome app of yours a version.

Your final package.json should look something like this:

{
"name": "myAwesomeApp",
"version": "0.1.0",
"private": true,
"scripts": {
"start": "pm2 start pm2_configs/config.json",
"dev": "pm2-dev start pm2_configs/config.json"
},
"dependencies": {
"body-parser": "~1.15.1",
"cookie-parser": "~1.4.3",
"debug": "~2.2.0",
"express": "~4.13.4",
"morgan": "~1.7.0",
"pug": "^2.0.0-beta11",
"serve-favicon": "~2.3.0"
}
}

For a non-logging, daemonised start (running the app in the background and returning control to the terminal), use npm start and to run your app in development mode, use npm run dev, it’s just a recommendation so you don’t go bananas while trying to figure out what broke and when.

Seems good for the time being. Onto Part 2.

--

--