DEV Community

Anusha Kuppili
Anusha Kuppili

Posted on

Containerizing a MERN Stack App with Docker Compose

Hey folks! πŸ‘‹

If you've ever tried deploying a MERN stack app (MongoDB, Express, React, Node.js), you’ve probably run into some challenges juggling all the services locally or in production. The solution? Docker Compose! 🐳

In this post, I’ll walk you through how to containerize a MERN stack app using Docker Compose and follow a 3-tier architecture: frontend (React), backend (Express + Node.js), and the database (MongoDB).

Let’s go! πŸ’ͺ

🧠Why 3-Tier Architecture?
Before we get our hands dirty, here's how the MERN stack maps to a 3-tier system:

Presentation Layer – React.js (handles the UI)

Business Logic Layer – Node.js + Express (handles API logic and routing)

Data Layer – MongoDB (stores and retrieves data)

Keeping these layers separate helps in scaling, debugging, and managing services better. Plus, it’s how things work in production environments.

πŸ“ Folder Structure

mern-app/
β”œβ”€β”€ backend/
β”‚   β”œβ”€β”€ Dockerfile
β”‚   └── server.js
β”œβ”€β”€ frontend/
β”‚   β”œβ”€β”€ Dockerfile
β”‚   └── src/
β”œβ”€β”€ docker-compose.yml
Enter fullscreen mode Exit fullscreen mode

πŸ”¨** Dockerizing Each Layer
πŸ›’οΈ MongoDB (Database Layer)**

Add this to your docker-compose.yml:

mongodb:
  image: mongo
  container_name: mongo
  ports:
    - "27017:27017"
  volumes:
    - mongo-data:/data/db
Enter fullscreen mode Exit fullscreen mode

βš™οΈ Backend – Express + Node.js (Business Layer)
Dockerfile (/backend/Dockerfile)

FROM node:18
WORKDIR /app
COPY . .
RUN npm install
EXPOSE 5000
CMD ["node", "server.js"]
Enter fullscreen mode Exit fullscreen mode

Compose Service

backend:
  build: ./backend
  ports:
    - "5000:5000"
  environment:
    - MONGO_URI=mongodb://mongo:27017/mydb
  depends_on:
    - mongodb
Enter fullscreen mode Exit fullscreen mode

🎨 Frontend – React.js (Presentation Layer)
Dockerfile (/frontend/Dockerfile)
Dockerfile

FROM node:18
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build
RUN npm install -g serve
CMD ["serve", "-s", "build", "-l", "3000"]
Enter fullscreen mode Exit fullscreen mode

Compose Service

frontend:
  build: ./frontend
  ports:
    - "3000:3000"
  depends_on:
    - backend
Enter fullscreen mode Exit fullscreen mode

🧩 Final docker-compose.yml

version: '3'
services:
  mongodb:
    image: mongo
    container_name: mongo
    ports:
      - "27017:27017"
    volumes:
      - mongo-data:/data/db

  backend:
    build: ./backend
    ports:
      - "5000:5000"
    environment:
      - MONGO_URI=mongodb://mongo:27017/mydb
    depends_on:
      - mongodb

  frontend:
    build: ./frontend
    ports:
      - "3000:3000"
    depends_on:
      - backend

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

πŸ§ͺ Run the App
From the root of your project, just run:

docker-compose up --build
Enter fullscreen mode Exit fullscreen mode

And that’s it! Your MERN app is now running across 3 separate containers πŸš€

Frontend β†’ http://localhost:3000

Backend API β†’ http://localhost:5000

MongoDB β†’ Running internally on port 27017

βœ… Wrapping Up
Docker Compose makes developing and deploying full-stack apps much more manageable. Whether you're working solo or on a team, containerizing your app ensures consistency and scalability across environments.

Let me know in the comments if you found this guide helpful or need help with any part of your setup. πŸ‘‡

Top comments (1)

Collapse
 
sai_nagasumalyapatnala_ profile image
Sai Naga Sumalya Patnala

Need more of these!