MERN Stack Deployment on Docker

To understand about deploying MERN stack using docker

MERN is a short form for MongoDB, Express, ReactJS and NodeJS. It represents a full-stack application. Each component in this stack has its usage given below,

MongoDB: A NoSQL document DB that stores data in the form of JSON. As most of the application uses JSON form of the data model, this database gives immense power in managing application data. The data is stored in Collection, which is analogous to Table in the relational database.

ReactJS: A declarative way of developing a web application. It encapsulates view with event handlers and other functionalities inside a component and helps faster development.

NodeJS: Quick and easy-to-learn server-side JavaScript environment.

ExpressJS: NodeJS package (something like a plugin) which can work as a web server.

About This Lab

This hands-on lab is about deploying a MERN stack on Docker. 

First, we will deploy a MongoDB container, then a container  with ReactJSNodeJS, and ExpressJS code that connects to MongoDB, and then do end-to-end testing.

Note: For your convenience all the required files are already created and are archived  in containerize.tar file in the home folder

Pre-requisites

The learner must have,

  1. docker latest version
  2. docker-compose latest version

For your convenience these softwares are pre-installed.

MERN Stack Application Use-case

The application that we are creating has the below use case:

1. User clicks on Web Application URL Link, and when the page loads in a browser, the user will see a list of names if there are any names in the database, else an empty single-column table with header Name is displayed.

2. There is a text box on the top of the table where the user can enter the name to add to the list. Users can enter the name and click the Add button.

3. Once the user clicks the button, application will save the name in the database and also it will be displayed in the list.

End-to-End Flow

Below is a brief end-to-end application flow:

Figure 1: End to End flow of the application
Figure 1: End to End flow of the application

1. The ReactJS application will handle the front-end part of the use case. It can make API (Application Program Interface) call to the backend nodeJS server with HTTP GET request to get all the names and an HTTP POST request to send the new name.

2. The NodeJS server will handle the initial URL load request to return the HTML file and the requests sent from the ReactJS application to retrieve-data-from OR save-data-to MongoDB as per the request.

Lab With MERN Stack on Docker

Extract the tar file

We have provided containerize.tar file containing all resources required to execute this lab in the home directory. So, first, you have to un-tar it with the below command.

tar -xvf containerize.tar

You should see a docker-compose.yml file and containerize folder in the home directory.

Deploying MongoDB

We deploy a single node instance of MongoDB. Below is the service definition in the docker-compose file.

docker-compose.yml

version: '2'
services:
  mongodb:
    container_name: 'mongodb-standalone'
    image: mongo:4.0.8
    environment:
      - MONGO_INITDB_ROOT_USERNAME=admin
      - MONGO_INITDB_ROOT_PASSWORD=password
    ports:
      - 27017:27017

Note: For convenience this already exists in the docker-compose.yml file in the home folder.

Run the below commands, to run mongodb container,

docker-compose up -d mongodb

Test if the MongoDB is up and running correctly, using the below commands

########################################
# open shell inside mongoDB container
########################################
docker exec -it mongodb-standalone sh

########################################
# connect to mongoDB server
########################################
mongo

#############################################
# log in with credentials, after connecting
#############################################
use admin
db.auth('admin','password')

#############################################
# disconnect and logout from the mongodb 
# container with exit command until you see
# command prompt root@master
#############################################

You should see the results below after running the commands,

Figure 2: Testing connectivity and access to MongoDB
Figure 2: Testing connectivity and access to MongoDB

Deploying ReactJS, NodeJS, and ExpressJS

This step assumes the learner has completed the hands-on lab given in pre-requisite section of this lab.

At this step, you should know how to containerize the ReactJS application with NodeJS and ExpressJS.

The ReactJS and NodeJS code used in this lab works with MongoDB.

Use the ReactJS and NodeJS code given below to create a container.

We have used the ReactJS code fromthisGitHub project. For convenience, this has already been built and the output build directory has been copied to containerize/server directory in the home folder (will be visible after the un-tar of containerize.tar file).

For convenience, all of the scripts/files used can be found in the containerize directory in this hands-on lab.

You should see the below items in the containerize directory (will be visible after the un-tar of containerize.tar file),

  • Dockerfile
  • server/package.json
  • server/index.js
  • server/build/

The NodeJS server code is in server/index.js. The file contents are as below

var MongoClient = require('mongodb').MongoClient;
const express = require('express');
const path = require('path');
const app = express();
const bodyParser = require("body-parser");

var url = process.env.MONGO_URL || "mongodb://admin:password@localhost:27017/";

app.use(express.static(path.join(__dirname, 'build')));
app.use(bodyParser.json());

app.get('/', function (req, res) {
  res.sendFile(path.join(__dirname, 'build', 'index.html'));
});

app.get('/test',function(req,res){
	console.log('testing....');
	MongoClient.connect(url, function(err, db) {
     console.log('Connected..',db,err);
     var dbo = db.db("mydb");
     dbo.createCollection("employee", function(err, res) {
    	if (err) throw err;
    	console.log("Employee Collection created!");
    	db.close();
  	});
  })
})

app.get('/api/emps', function (req, res) {
  MongoClient.connect(url, function(err, db) {
    if (err) throw err;
    var dbo = db.db("mydb");
    dbo.collection("employee").find().toArray(function(err, result) {
      if (err) throw err;
      console.log(result);
      db.close();
      res.send(result);
    });
  });
});

app.post('/api/emp', function (req, res) {
  MongoClient.connect(url, function(err, db) {
    if (err) throw err;
    var dbo = db.db("mydb");
    var myobj = { name: req.body.val };
    debugger;
    console.log('request',req.body)
    dbo.collection("employee").insertOne(myobj, function(err, result) {
      if (err) throw err;
      console.log("1 document inserted");
      db.close();
      res.send("Successfully added item!");
    });
  });
});

app.listen(9000);

Build the docker container

  • Instal the required packages using below command,
cd ~/containerize/server && npm install
  • To test node server is working fine, run the below command (in server directory),
cd ~/containerize/server && node index.js

Click on the Lab URLs named node on the right side. This will send a request to the node server listening to port 9000 and return the HTML to load on the browser.

Figure 3: App running on port 9000
Figure 3: App running on port 9000
Figure 4: Adding a user to the app
Figure 4: Adding a user to the app

Now stop the server by pressing the keys Ctrl + c

  • Build the docker container image for the react-node application
cd ~/containerize && docker build -t webapp:1.1 .

Here we named the image as webapp with version tag 1.1

Run the react-node docker container

To run the react-node docker container, the service configuration in docker-compose file is as below( exists in home folder),

docker-compose.yml

version: '2'
services:
  mongodb:
    container_name: 'mongodb-standalone'
    image: mongo:4.0.8
    environment:
      - MONGO_INITDB_ROOT_USERNAME=admin
      - MONGO_INITDB_ROOT_PASSWORD=password
    ports:
      - 27017:27017
  reactnode:
    container_name: "react-node"
    image: "webapp:1.1"
    working_dir: /home/node/app
    ports:
     - "30000:9000"
    environment:
    - MONGO_URL=mongodb://admin:password@mongod:27017/
    command: "npm start"

Run the react-node docker container with below command,

cd ~ && docker-compose up -d reactnode

Click on Lab URLs react-ui Link on the right side to access the front-end Application and test it out.

Figure 5: Application running as a container
Figure 5: Application running as a container

Conclusion

In this hands-on lab we accomplished below tasks,

  • Run a mongodb container
  • Get the App which uses ReactJS with NodeJS and ExpressJS
  • Do npm install and run the node server locally and test
  • Create a container image for ReactJS and NodeJS code
  • Run the container (react-node)
  • Test the app

What next?

As a next step the following things can be explored further,

  • How is mongoDB deployed in production environment ?
  • How can these MERN stack components can be deployed on Kubernetes platform ?

Resources

Play with Docker

MongoDB Tutorial

NodeJs Tutorial

React Tutorial

docker-compose documentation

Containerise ReactJS application with NodeJS

Kubernetes Basics

Join Our Newsletter

Share this article:

Table of Contents