How to Dockerize the MongoDB, Express, React, Node (MERN) Application for Efficient Development and Production using docker and docker-compose.
In the Last Blog, we learned about docker and docker-compose and how we can use these great technologies for container orchestration and efficient development and Production.
In this Practical blog we will understand how we can dockerize the hottest tech stack right now, yeah you heard right MERN Stack which stands for MongoDB, Express, React, and Node using docker and docker compose.
So before diving into practical let’s first understand what is this MERN stack. In the MERN stack M stand for MongoDB which is a Database, unlike traditional SQL-based databases, MongoDB is a NoSQL database which is a very scalable database with very high performance (we will discuss those in the next blog). So we will use MongoDB to store our application data.
E stands for Express which is the framework for API development and other backend-related tasks.
R stands For React which is javascript based frontend library for building reusable high-performance user interfaces
N stands for the node which is the Javascript runtime for backend applications it uses chrome’s v8 engine to run javascript on the machine.
Now let’s jump to practical directly.
So first we will build two projects:
- A simple Node-based Project: it has 2 APIs for Adding User and Getting User and we will store MongoDB to store the user’s data.
- React Project: To consume these APIs and work as a frontend to show and ingest data.
Then after that, we will dockerize three services:
- MongoDB database
- Backend
- Frontend
We will use Docker Compose with docker to dockerize the application.
Now let’s Start Dive into the Backend:
This is Our Index.ts file, which is the main file in which we are serving our backend application and connecting to the database.
This is Our App.tsx for Frontend React.
I will not deep dive into the Project Setup and How to Create these Projects, this blog is about dockerization so our focus will be that only.
You can checkout this repo for the whole source code:
Now to dockerize both applications, we will write the docker file for both of the applications
Frontend dockerfile
The Above Code is for dockerizing the react application.
So let’s understand that line by line:
FROM node
- To specify node as a base image because react uses node as the environment. so we need that.
WORKDIR /app
- To defining the app in the docker file system as a working directory (it will create that directory if not exists)
COPY package.json .
- To copy package.json into the current directory which is the app directory (we are copying package.json first because docker uses the layering approach for handling changes we do not change the package.json and rebuild the image container so the package.json needn’t be copied again).
COPY . .
- For copying everything into the current directory.
RUN npm install
- To the install package.json dependencies
EXPOSE 3000
- To expose port 3000 inside the docker container.
CMD ["npm"," start"]
- To now run the npm start script to run the application
Backend dockerfile:
the above code is for the backend in this we are exposing port 5000 and running a different start script.
docker-compose file:
Now coming to the docker-compose file.
Now let’s understand docker-compose.yaml line by line:
version: "3.8"
- describes the version of docker-compose syntax we are using version: “3.8” which is the latest at the time of writing this blog.
services:
- define services: which are DB, frontend, and backend for our 3 services.
db:
image: mongo
- defines MongoDB image: “mongo” to install for db which is binary for the mongodb dabase
volumes:
- db_data:/data/db
- defines a volume for persisting data for DB so if the image container is stopped and we would not lose the data
ports:
- "27017:27017"
- exposes the port of the db which is 27017 in our case. ports follow: “port_to_exposed_on_localhost”:“port_to_exposed_inside_docker_contianer” convention.
backend:
- backend defines the backend service.
env_file:
- .env
- env_file to choose to expose the environment variables to use inside the application.
build:
context: ./docker_node
dockerfile: backend.dockerfile
- built command used to build the docker file. context is the path to the docker file we defined for the backend and frontend
ports:
- "5000:5000"
- exposes the port which is 5000 in this case.
depends_on:
- db
- defines that the backend depends on the db because it needs to wait for the database to be ready before connecting.
volumes:
- ./docker_node/src:/app/src
- defines the bind mount which is also a volume for live reloading the application.
frontend:
build:
context: ./docker_react
dockerfile: frontend.dockerfile
ports:
- "3000:3000"
depends_on:
- backend
stdin_open: true
tty: true
volumes:
- ./docker_react/src:/app/src
- Same thing for the frontend application but we need to add two extra arguments tty and stdin for running the container in the interactive mode.
volumes:
- ./docker_react/src:/app/src
- the last line is we define the volumes we defined in the docker-compose.
Now to run these containers we have use some commands which are as follows:
docker-compose build
to build the dockerfiles: backend.dockerfile and frontend.dockerfile in our case.
docker-compose up
to start the container and that’s it now you are running the MERN application in a dockerized environment. Which is a Highly Efficient Method for development and Production.
docker-compose down
for destroying the containers after you are done and you can use docker-compose up to run the container again.
This is Running Application Screenshots:
That’s it for today guys, you learned a new thing today good for you. Give a nice pat to yourself on the back, Have Some coffee and watch naruto if you haven’t started. Right now I am watching and it’s awesome.
See you tomorrow for a new blog and new learning. Until then check out my other blog I am sure it will help you learn new technology fast and easily.