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 ReactJS, NodeJS, 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,
- Hands-on knowledge of docker containers and docker-compose tools.
- Basic knowledge of MongoDB
- Completed the hands-on-lab Containerising ReactJS application with NodeJS
- Make sure the below softwares are installed:
- docker latest version
- 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](https://cyold.cloudyuga.guru/rails/active_storage/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaEpJaWsyWTJNNFkyRTJPUzA0TW1JeUxUUmhNVEV0T0RNeE15MWxNakE1TWpjMFl6RXpNalFHT2daRlZBPT0iLCJleHAiOm51bGwsInB1ciI6ImJsb2JfaWQifX0=--416d4fd1a2aa67135a533f7e44d68419156b5838/MERN.png)
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](https://cyold.cloudyuga.guru/rails/active_storage/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaEpJaWxsT1Rnek9HRTJZaTA1TldRM0xUUm1ZelF0WW1GbE9TMWxNemxtWVdFMVl6ZG1NV1VHT2daRlZBPT0iLCJleHAiOm51bGwsInB1ciI6ImJsb2JfaWQifX0=--2867a89559c4e190465184632d219a158dc4e6f5/Screenshot%20(207).png)
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.
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.
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 ?