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!