Building a Node Js Application and deploying through Docker: Express Myself
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.