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
π¨** 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
βοΈ Backend β Express + Node.js (Business Layer)
Dockerfile (/backend/Dockerfile)
FROM node:18
WORKDIR /app
COPY . .
RUN npm install
EXPOSE 5000
CMD ["node", "server.js"]
Compose Service
backend:
build: ./backend
ports:
- "5000:5000"
environment:
- MONGO_URI=mongodb://mongo:27017/mydb
depends_on:
- mongodb
π¨ 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"]
Compose Service
frontend:
build: ./frontend
ports:
- "3000:3000"
depends_on:
- backend
π§© 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:
π§ͺ Run the App
From the root of your project, just run:
docker-compose up --build
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)
Need more of these!