MERN Stack Explained: A Complete Guide with Docker

MERN stack explanation + example with docker

The MERN stack is a popular combo of technologies used to build full-stack web applications. It’s made up of four main parts:

  1. MongoDB – A NoSQL database that stores data in a flexible, JSON-like format. It’s perfect for handling lots of data or complex relationships.
  2. Express.js – A web framework for Node.js that simplifies building backend logic, APIs, and handling server requests/responses.
  3. React – A JavaScript library for building user interfaces. It focuses on creating dynamic, interactive views for users.
  4. Node.js – A runtime that lets you run JavaScript on the server side.

Together, they provide a seamless way to create modern web apps. React handles the front-end (what users see), while Express and Node manage the back-end (server-side logic). MongoDB stores the app’s data, and it all works in JavaScript, making it super developer-friendly.

It’s like a one-stop shop for web development! BUT like every framework it has cons and pro’s

The cons and the pro’s

The MERN stack has its ups and downs. On the pro side, it’s JavaScript all the way through, making it easier for developers to work on both the front and back end without needing to switch languages. It’s also highly flexible, allowing you to create everything from small apps to large-scale projects. Plus, with React’s efficient rendering and MongoDB’s ability to handle unstructured data, it’s great for modern, dynamic applications.

The MERN stack—combining MongoDB, Express.js, React, and Node.js—offers a seamless, JavaScript-driven ecosystem ideal for building modern, scalable web applications with a unified language, flexible data handling, and efficient performance from backend to frontend.

On the downside, managing all these parts together can be tricky, especially for beginners. Scaling can also get complex if your app grows quickly, as MongoDB isn’t always the best for relational data. And while flexibility is great, it can mean there’s no clear “one way” to do things, which might slow down development for some teams.

The MERN stack may not be the best choice if your project requires relational databases, server-side rendering out of the box, or if your team lacks proficiency in JavaScript.

Fortunately for us, we use this stack as an API and not as a full blown server/backend language

The Importance of RESTful APIs in MERN Applications

In MERN applications, RESTful APIs play a crucial role as the communication bridge between the frontend and backend. They enable seamless data exchange, maintain a stateless architecture, and support scalable development, making them an essential component of modern web applications.

What Makes REST Tick?

REST, or Representational State Transfer, is guided by principles like stateless communication, a clear separation between client and server, and the use of uniform interfaces. Following these principles ensures APIs are consistent, efficient, and easy to maintain, which is key to building robust applications in the MERN stack.

setting op MERN stack

Prerequisites

Before we begin, make sure you have the following installed on your system:

install all the following packages to move forward

npm install express mongoose cors

Your folder should look like this

For this example, we will assume the following structure for our MERN application:

mern-app/
|-- backend/  (Node.js + Express API)
|-- frontend/ (React App)
|-- docker-compose.yml
|-- Dockerfile (for backend)
|-- .env

Backend – Creating a Dockerfile

We first need to containerize our Node.js + Express backend by creating a Dockerfile inside the backend/ directory.

backend/Dockerfile

# Use an official Node.js runtime as a parent image
FROM node:18-alpine

# Set the working directory in the container
WORKDIR /app

# Copy package.json and package-lock.json
COPY package*.json ./

# Install dependencies
RUN npm install

# Copy the rest of the application code
COPY . .

# Expose the application port
EXPOSE 5000

# Start the server
CMD ["npm", "start"]

Frontend – Creating a Dockerfile

To containerize the React frontend, create a Dockerfile inside the frontend/ directory.

frontend/Dockerfile

# Use an official Node.js runtime as a parent image
FROM node:18-alpine

# Set the working directory
WORKDIR /app

# Copy package.json and package-lock.json
COPY package*.json ./

# Install dependencies
RUN npm install

# Copy the rest of the app
COPY . .

# Build the React app
RUN npm run build

# Install a simple web server
RUN npm install -g serve

# Expose port 3000
EXPOSE 3000

# Serve the application
CMD ["serve", "-s", "build", "-l", "3000"]

Creating a Docker Compose File

Now that both backend and frontend Dockerfiles are set up, let’s define Docker Compose to orchestrate the services.

docker-compose.yml

version: '3.8'

services:
  mongodb:
    image: mongo:latest
    container_name: mongo_container
    restart: always
    environment:
      MONGO_INITDB_ROOT_USERNAME: admin
      MONGO_INITDB_ROOT_PASSWORD: password
    ports:
      - "27017:27017"
    volumes:
      - mongo_data:/data/db

  backend:
    build: ./backend
    container_name: backend_container
    restart: always
    depends_on:
      - mongodb
    ports:
      - "5000:5000"
    environment:
      MONGO_URI: mongodb://admin:password@mongodb:27017/

  frontend:
    build: ./frontend
    container_name: frontend_container
    restart: always
    depends_on:
      - backend
    ports:
      - "3000:3000"

volumes:
  mongo_data:

Running the MERN Stack with Docker Compose

Once the Dockerfile and docker-compose.yml are set up, you can start the MERN stack by running the following command in the project root directory:

docker-compose up -d --build

This command builds the images and starts the containers in detached mode (-d).

Verifying the Setup

After running the above command, verify that everything is running correctly:

docker ps

You should see mongo_container, backend_container, and frontend_container running.

To access your application:

Conclusion

Dockerizing your MERN stack application provides a consistent environment for development and deployment. With Docker Compose, managing multi-container applications becomes seamless. This guide provided a step-by-step approach to containerizing a MERN stack and running it with Docker Compose.

Next Steps you can do

  • Push the Docker images to Docker Hub for easy deployment.
  • Deploy the application using Kubernetes for scalability.
  • Use NGINX as a reverse proxy to streamline the deployment.
Scroll to Top