Day-29.1-devops

Containerizing a MERN Stack Application with Docker Compose: A Comprehensive Guide

This guide provides a step-by-step approach to containerizing a MERN stack application using Docker Compose. It covers the architecture of a MERN stack, the creation of Dockerfiles for frontend and backend services, and the deployment process using Docker Compose, ensuring seamless communication between containers.

In this guide, we will explore how to containerize a MERN stack application and deploy it in a Docker environment using Docker Compose. If you're unfamiliar with the MERN stack, don't worry; we will cover its architecture and components in detail. By the end of this guide, you will learn how to write Dockerfiles for different services, set up a MongoDB database as a container, and deploy everything using Docker Compose.

Understanding the MERN Stack

What is the MERN Stack?

The MERN stack is a popular web development stack that consists of four main technologies:

  • MongoDB: A NoSQL database that serves as the data layer.

  • Express.js: A web application framework for Node.js that handles the backend logic.

  • React.js: A JavaScript library for building user interfaces, serving as the frontend layer.

  • Node.js: A JavaScript runtime that allows you to run JavaScript on the server side.

Three-Tier Architecture

The MERN stack follows a three-tier architecture, which includes:

  1. Presentation Layer: The UI or frontend, where users interact with the application.

  2. Business Logic Layer: The backend, where the application logic is processed.

  3. Data Layer: The database, where data is stored and retrieved.

For example, in an e-commerce application like Amazon, the user interacts with the UI (frontend), which communicates with the backend (business logic) to fetch product details from the database (data layer).

Setting Up the Project

Before we dive into containerization, let's take a look at the project structure. We have two branches in our GitHub repository:

  • Main Branch: Contains the source code and instructions to run the application locally without Docker.

  • Compose Branch: Contains the Dockerfiles and Docker Compose setup that we will create in this guide.

Writing Dockerfiles

Frontend Dockerfile

To containerize the frontend, we will create a Dockerfile in the frontend directory. Here are the steps:

  1. Start with the official Node.js image.

  2. Set the working directory to /app.

  3. Copy the package.json file and install dependencies using npm install.

  4. Copy the rest of the source code.

  5. Expose the port that the application will run on (5173).

  6. Define the command to run the application (npm run dev).

Backend Dockerfile

Similarly, we will create a Dockerfile for the backend:

  1. Use the same Node.js image.

  2. Set the working directory to /app.

  3. Copy the package.json file and install dependencies.

  4. Copy the source code.

  5. Expose the backend port (5050).

  6. Define the command to start the backend application (npm start).

Running MongoDB as a Container

Before running the backend, we need to start the MongoDB container. This can be done using the following command:

docker run --name mongodb -d -p 27017:27017 mongo:latest

This command runs MongoDB in detached mode and maps the default MongoDB port.

Creating a Docker Network

To allow communication between the frontend, backend, and database containers, we will create a Docker network:

docker network create mern-network

Running the Containers

After setting up the Dockerfiles and the MongoDB container, we can run the frontend and backend containers. Make sure to connect them to the same network:

docker run --name frontend --network mern-network -p 5173:5173 frontend-image

docker run --name backend --network mern-network -p 5050:5050 backend-image

Using Docker Compose

To simplify the process of running multiple containers, we will use Docker Compose. This allows us to define all services in a single YAML file. Here’s how to create a docker-compose.yml file:

Docker Compose File Structure

  1. Services: Define each service (frontend, backend, and MongoDB) with their respective configurations.

  2. Networks: Specify the network that the services will use.

  3. Volumes: Define any volumes needed for persistent data storage.

Example Docker Compose Configuration

version: '3'
services:
  frontend:
    build:
      context: ./frontend
    ports:
      - "5173:5173"
    networks:
      - mern-network

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

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

networks:
  mern-network:
    driver: bridge

volumes:
  mongodb-data:
    driver: local

Running Docker Compose

To start all services defined in the docker-compose.yml file, simply run:

docker-compose up -d

This command will build and start all containers in detached mode, ensuring they are connected to the specified network.

Conclusion

In this guide, we have successfully containerized a MERN stack application using Docker Compose. We covered the architecture of the MERN stack, created Dockerfiles for the frontend and backend, set up a MongoDB container, and simplified the deployment process using Docker Compose. This approach not only streamlines development but also ensures that all components can communicate effectively within a defined network.

For further exploration, refer to the Compose branch in the GitHub repository for complete code and configurations. Thank you for following along, and happy coding!