Containerizing MERN Stack Application - Docker Compose

Mern is a 3 Tier architecture application is an end to end application

  1. Presentation Layer ( UI/Frontend)

  2. Business Logic ( Server/Backend)

  3. Database

Example: Amazon.com also is a 3 tier application

Steps to Containerize the application with details

  1. Clone the github repository

      git clone https://github.com/amitsinghs98/MERN-docker-compose.git
    
  2. First, we will write our 3-tier application into a Dockerfile, and later we will adjust both the Dockerfile for the Frontend and Backend using Docker Compose.

    Dockerfile for frontend :

     FROM node:18.9.1 # We will use the hardcoded value of node version instead of latest, 
     # because if we move the application on production we won't face the version issue
    
     WORKDIR /app  #Everything of our container will be stored in app directory
    
     COPY package.json .     #will add dependencies in /app/package.json
    
     RUN npm install         #The dependencies we have added above to /app dir, will install 
    
     COPY . .                #Copy source code to /app workdir now
    
     EXPOSE 5173
    
     CMD ["npm","run","dev"]    # for reference check package.json file in mern file
    

    Note:( Dependencies file in diff languages)

    python: requirements.txt
    java: pom.xml
    Golang: go.mod
    node: package.json

Before going further, create “Network” with name = mern

sudo docker network create mern

When multiple containers are there, frontend, backend, database: network help to bind these three container on a same pace. Makes communication easy between them.

By default we get “bridge” network to connect host and container.

Now create the docker image with help of Docker file :

docker build -t mern-frontend. 
docker run --name=frontend --network=mern -d -p 5173:5173 mern-frontend

As you can see, our frontend is running, but if you try to save a record, it won't work because we haven't connected the database and backend yet.

So, to recap, here are the steps to build this application using Docker containers:

  1. Create a Dockerfile for the frontend.

  2. Run a database container with MongoDB; there's no need to create it with a Dockerfile.

  3. Create a Dockerfile for the backend. We do this last because the backend depends on the database.

3. Run docker container for mongoDB database

docker run --network=mern --name=mongodb -d -p 27017:27017 -v ~/opt/data:/data/db mongo:latest

4. Write Dockerfile for backend

FROM node:18.9.1
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
EXPOSE 5050
CMD ["npm","start"]
docker build -t mern-backend . 
docker run --network=mern --name=backend -d -p 5050:5050 mern-backend

Go to URL: localhost:5173/create

Points to note:

  1. By default dockers comes with the bridge network

  2. Run Frontend Container → Run Database Container → Run Backend Container

Now Integrate all in Docker Compose

Instead of running multiple commands, we create a single Docker Compose YAML file to manage the multi-container application. This file specifies dependencies to ensure the application runs smoothly.

  1. Manage container dependencies.

  2. Use a common network for containers.

// This will remove all the above containers and create a Docker Compose file. File should be at root level

For Ubuntu & Debian first install Docker compose

1️⃣ Update your package list:

sudo apt update

2️⃣ Install Docker Compose:

sudo apt install docker-compose -y

3️⃣ Verify the installation:

docker-compose --version

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

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

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

networks:
  mern:
    driver: bridge

volumes:
  mongo-data:
    driver: local