Logo

dev-resources.site

for different kinds of informations.

Containerizing a MERN Stack Application!

Published at
1/3/2025
Categories
docker
devops
node
mongodb
Author
yash_patil16
Categories
4 categories in total
docker
open
devops
open
node
open
mongodb
open
Author
12 person written this
yash_patil16
open
Containerizing a MERN Stack Application!

In this blog, I’ll walk you through a simple yet powerful project that demonstrates the MERN stack in action. We will go through what MERN is but also how it works together to create a robust application. Plus, we’ll explore how Docker helps containerize and orchestrate everything seamlessly.

Here is the Github link for the project which consists of the source code and the Docker-Compose file used to containerize the application.

Image description

NOTE: This application is an open-source project to showcase the process of containerizing existing applications.

Before beginning to containerize the application lets first understand what is MERN framework is and its architecture and structure and how it works.

What is MERN?

MERN stands for MongoDB, Express.js, React, and Node.js—a popular stack for building full-stack JavaScript applications. Here’s how each component contributes:

  1. MongoDB: A NoSQL database that stores data in JSON-like documents, and acts as the database layer.

  2. Express.js: A lightweight web framework for Node.js, used to build business logic of the application and manage HTTP requests and define API endpoints.

  3. React: A frontend library for building dynamic and responsive user interfaces and client side logic. It fetches data from the backend via REST API or graphQL.

  4. Node.js: A JavaScript runtime environment that powers the backend, enabling JavaScript to run on the server. It acts a virtual server on top of our servers or host system on which the application might be hosted. Hence it hosts the application, allowing it to run and be accessed over the internet.

Together, MERN allows developers to write the entire application in JavaScript, streamlining the development process.

For this basic MERN stack application which allows us to Create, View, Edit and Delete employee records, we have a frontend and a backend folder.

The backend of this MERN stack application is designed to handle data operations for managing employee records. Here’s a breakdown of how the connection.js, records.js, and server.js files interact to make everything function seamlessly.

Image description

1. Database Connection: /db/connection.js

This file establishes a connection to the MongoDB database.

  • Client : In this case, the database server is named mongodb (as defined in the docker-compose.yml file), and it listens on port 27017. This the database connection string and we can also read this connection string using a environment variable or a config file.

Image description

  • Database Reference: The employees database is referenced using client.db("employees"), and this reference is exported as db. This enables other parts of the application, such as API routes, to interact with the database.

Image description

2. API Routes: records.js

The records.js file defines a set of RESTful API endpoints for CRUD operations (Create, Read, Update, Delete). These routes use the express.Router to group and manage endpoints under the /record path and defines RESTful routes to handle requests for employee data using the db object.

3. Server Initialization: server.js

The server.js file is the entry point for the backend application.

Image description

  • Express App: An Express application is created to handle HTTP requests and responses.

  • Middleware:

    • cors: Enables Cross-Origin Resource Sharing, allowing the frontend (on a different port) to communicate with the backend.
    • express.json: Parses incoming JSON payloads in request bodies.
  • Route Mounting: The records routes are mounted at the /record path. For example, a request to /record is handled by the logic defined in records.js.

  • Server Startup: The app listens on port 5050 (or another port if specified in the PORT environment variable). A message is logged to confirm the server is running.

So basically that sums up the backend logic of the application.

  • When a request is made from the browser using the REACTjs frontend application, the Nodejs listens for the incoming HTTP requests on a specified port.

  • Passes the request to Express.js which matches the request to the defined route.

  • It executes the corresponding logic, like querying(CRUD operations) the database or prepare a response, etc.

  • Then Node takes the response by Express.js and sends it back to the Browser where it is displayed to the user via the React.js frontend application.

And that’s the actual workflow of a MERN stack application.

Containerizing the Application

What is Docker Compose?

Docker Compose is a tool that simplifies the management of multi-container applications. Using a docker-compose.yml file, you can define and configure services, networks, and volumes needed for your application. With a single command, Docker Compose can build, start, and orchestrate all the containers defined in the file.

Now lets begin to containerize the application. The docker-compose.yml file orchestrates the three services (frontend, backend, and MongoDB) to work together seamlessly. I have created Dockerfiles for both the frontend and the backend which we will run as separate containers and create a MongoDB container using a image from the DockerHub.

services:
  frontend:
    build: ./mern/frontend
    ports:
      - "5173:5173"
    networks:
      - mern

  backend:
    build: ./mern/backend
    ports:
      - "5050:5050"
    networks:
      - mern
    depends_on:
      - mongodb

  mongodb:
    image: mongo
    ports:
      - "27017:27017"
    networks:
      - mern
    volumes:
      - mongo-data:/data/db

networks:
  mern:
    driver: bridge

volumes:
  mongo-data:
    driver: local
Enter fullscreen mode Exit fullscreen mode

Frontend Service:

- build: ./mern/frontend`: Specifies the Dockerfile for the frontend 
   application located in the `mern/frontend` directory.

- ports: "5173:5173"`: Maps port 5173 on the host to port 5173 in the container, making the React app accessible.

- networks: `mern`: Connects the service to the `mern` network for inter-service communication.
Enter fullscreen mode Exit fullscreen mode

Backend Service:

* `build: ./mern/backend`: Specifies the Dockerfile for the backend application located in the `mern/backend` directory.

* `ports: "5050:5050"`: Maps port 5050 on the host to port 5050 in the container for backend access.

* `depends_on: mongodb`: Ensures MongoDB starts before the backend.

* `networks: mern`: Connects the service to the `mern` network.
Enter fullscreen mode Exit fullscreen mode

MongoDB Service:

* `image: mongo`: Uses the official MongoDB image to run the database.

* `ports: "27017:27017"`: Maps port 27017 on the host to port 27017 in the container for database access.

* `volumes: mongo-data:/data/db`: Mounts a Docker volume named `mongo-data` to `/data/db` inside the container for persistent storage. The volume is mounted to `/data/db` inside the MongoDB container because `/data/db` is the default directory used by MongoDB to store its database files.

* `networks: mern`: Connects the service to the `mern` network.
Enter fullscreen mode Exit fullscreen mode

Networks:

* `mern`: A custom bridge network allowing the frontend, backend, and MongoDB services to communicate.
Enter fullscreen mode Exit fullscreen mode

Volumes:

* `mongo-data`: A named volume to persist MongoDB data between container restarts. This volume is created under `/var/lib/Docker/volumes`
Enter fullscreen mode Exit fullscreen mode

Now make sure you are in the directory where the docker-compose.yml is present and use to following command to spin up all the containers :

docker-compose up
Enter fullscreen mode Exit fullscreen mode

Note: For the first time it may take some time to build the images and run the containers.

Image description

Now access the frontend application at localhost:5173 where out React frontend application is running.

Image description

Image description

Now even if i stop and recreate all the containers, the records will still be there since we have used a host volume and mounted it to the mongoDB container. This allows the data persistence.

Stop all containers using :

docker-compose down
Enter fullscreen mode Exit fullscreen mode

Image description

And that’s how easy it is to work with docker compose in a multi container environment.

Summary

  1. Frontend: A React app running on port 5173, providing a user-friendly interface for managing employee records.

  2. Backend: A Node.js API on port 5050, processing business logic and interacting with MongoDB.

  3. Database: MongoDB, configured with a connection URL and persisting data via a Docker volume.

  4. Docker Compose: Orchestrates the entire stack, making it easy to spin up the application.

Going forward the entire workflow of a MERN stack application is pretty much similar with a few teaks here and there but the logic remains the same.

Always make sure the to go through the application codebase and understand how the application works before proceeding forward which will make it easy to use tools like Docker or Docker-Compose.

Feel free to checkout my blog : yashpatilofficial.hashnode.dev & dev.to/yash_patil16

And connect with me at LinkedIn : https://www.linkedin.com/in/yash-patil-24112a258/

mongodb Article's
30 articles in total
Favicon
🌐 Building Golang RESTful API with Gin, MongoDB 🌱
Favicon
Construindo uma API segura e eficiente com @fastify/jwt e @fastify/mongodb
Favicon
Making a Todo API with FastAPI and MongoDB
Favicon
How to Create and Consume a REST API in Next.js
Favicon
Crudify: Automate Your Mongoose CRUD Operations in NestJS
Favicon
Utilizando la librería Mongoose
Favicon
Full Stack Development (Mern && Flutter)
Favicon
Node.js Meets PostgreSQL and MongoDB in Docker: Docker Diaries
Favicon
Comprendre le Design Pattern MVC avec Node.js, Express et MongoDB
Favicon
Set up MongoDB primary and secondary with Docker.
Favicon
The Intricacies of MongoDB Aggregation Pipeline: Challenges and Insights from Implementing It with Go
Favicon
Test Post
Favicon
Containerizing a MERN Stack Application!
Favicon
MongoDB vs. Couchbase: Comparing Mobile Database Features
Favicon
6 Steps to Set Up MongoDB Atlas for Node.js Applications
Favicon
MongoDB: How to setup replica sets
Favicon
To Dockerize a Node.js and MongoDB CRUD app
Favicon
Day 39: Deploying Stateful Applications with StatefulSets (MongoDB)
Favicon
Do you think schema flexibility justifies using NoSQL? Think twice.
Favicon
HadiDB: A Lightweight, Horizontally Scalable Database in Python
Favicon
A Simple Guide for Choosing the Right Database
Favicon
Integrating MongoDB Atlas Alerts with Lark Custom Bot via AWS Lambda
Favicon
🔍 MongoDB Data Modeling: Embedding vs. Referencing - A Strategic Choice!
Favicon
Unique Index on NULL Values in SQL & NoSQL
Favicon
Embedding vs. Referencing - A Strategic Choice!
Favicon
Series de tiempo en MongoDB
Favicon
I want to write a code for POS sales output interface - and import to mongoDb for sale analysis- however is POS agnostic interface, should work with all POS
Favicon
Hello,help review my fullstack website stack : nestjs,mongodb and reactjs. https://events-org-siiv.vercel.app/
Favicon
Implementing an Express-based REST API in TypeScript with MongoDB, JWT-based Authentication, and RBAC
Favicon
It's a Security Thing.

Featured ones: