Photo by Shahadat Rahman on Unsplash

Building a MERN stack application can be challenging, especially when it comes to managing dependencies and different environments. Docker can help simplify this process by allowing developers to package their applications in containers, making them easy to move between different environments.

In this blog post, we will walk you through the process of containerizing a MERN stack application using Docker and Docker Compose. Docker and Docker Compose are two powerful tools that work together to simplify the development, deployment, and management of containerized applications.

Docker

Docker is a platform that enables you to package your application and its dependencies into standardized units called containers. These containers are lightweight and portable, meaning they can run consistently on any system with Docker installed, regardless of the underlying operating system.

Docker Compose

Docker Compose is a tool for defining and running multi-container applications with ease. It uses a YAML file (often named docker-compose.yml) to configure your application’s services (containers) and their relationships.

Before you begin, make sure you have the following installed on your system:

DockerNode.js

And I assume you have a basic understanding of docker and its commands.

Step 1: Set Up Your MERN Application

Assume you have a basic MERN application structured like this, and you need to create Dockerfile and docker-compose file like this:

my-mern-app/
├── backend/
│ ├── Dockerfile
│ ├── package.json
│ ├── server.js
├── frontend/
│ ├── Dockerfile
│ ├── package.json
│ ├── public/
│ ├── src/
├── docker-compose.yml

Step 2: Set up backend and frontend docker files

Backend Setup

You need to include the below instructions in the backend dockerfile.

# backend/Dockerfile

# Use an official Node.js Alpine-based image
FROM node:20.11.1-alpine

# Set the working directory
WORKDIR /app

# Copy package.json and package-lock.json
COPY package*.json ./

# Install dependencies
RUN npm install

# Copy the rest of the application code
COPY . .

# Expose the port the app runs on
EXPOSE 5000

# Start the application
CMD [“npm”, “start”]

As the base image for the container, I use the Node.js runtime, version 20.11.1, based on the Alpine Linux distribution. Alpine images are typically smaller and faster to download. WORKDIR /app sets the working directory inside the container to /app. All subsequent commands will be run from this directory. COPY package*.json ./ copies package.json and package-lock.json (if it exists) from your local machine to the container. These files are used to install the dependencies.

This runs npm install inside the container, installing all the dependencies specified in package.json. COPY . . copies the rest of your application code into the container’s working directory. EXPOSE 5000 informs Docker that the container will listen on port 5000 at runtime. This is useful for mapping this internal port to an external port on your host machine. CMD [“npm”, “start”] specifies the command to run when the container starts. It runs the Node.js application by executing npm start which typically starts your server using the start script defined in package.json.

Frontend Setup

You need to include the below instructions in the frontend Dockerfile.

# frontend/Dockerfile

# Use an official Node.js Alpine-based image
FROM node:20.11.1-alpine

# Set the working directory
WORKDIR /app

# Copy package.json and package-lock.json
COPY package*.json ./

# Set npm to have longer timeouts and use cache
RUN npm config set cache /app/.npm-cache –global
RUN npm config set fetch-retries 10
RUN npm config set fetch-retry-mintimeout 40000
RUN npm config set fetch-retry-maxtimeout 220000

# Install dependencies
RUN npm install

# Copy the rest of the application code
COPY . .

# Expose the port the app runs on
EXPOSE 3000

# Starting our application
CMD [“npm”,”start”]

When setting up Dockerfiles for both frontend and backend applications, you’ll find that most instructions are quite similar. The primary distinctions lie in the timeout and cache configurations. Depending on your specific needs, you may or may not require these additional steps.

Use a cache directory inside the container (/app/.npm-cache).Increase the number of retry attempts for fetching packages (fetch-retries).Set longer minimum and maximum timeouts for fetching packages (fetch-retry-mintimeout and fetch-retry-maxtimeout).

These settings can help improve reliability when downloading dependencies, especially in environments with unstable network connections. If you have an internet connection like I have might need this :(.

https://medium.com/media/2c9e12e3b7360dddff67f758042fbacd/href

Step 3: Set Up Docker Compose

You need to include the below configurations in the root docker-compose file.

# docker-compose.yml

version: ‘3.8’
services:
backend:
build: ./backend
ports:
– ‘5000:5000’
frontend:
build: ./frontend
ports:
– ‘3000:3000’

backend: Defines the backend service. It builds the Docker image from the backend directory and maps port 5000. frontend: Defines the frontend service. It builds the Docker image from the frontend directory and maps port 3000.

If you need to add more services like Mongo DB, you just need to add another service like this but it depends on the backend.

version: ‘3.8’
services:
backend:
build: ./backend
ports:
– ‘5000:5000’
depends_on:
– mongo
mongo:
image: mongo:latest
ports:
– ‘27017:27017’

Step 4:Build and Run the Application

In the root of your project, run the following command to build and start your application:

docker-compose up — build

Docker Compose will build the images and start the containers. You can access the frontend at http://localhost:3000 and the backend at http://localhost:5000. You can find the reference code here.

You have now successfully Dockerized your MERN stack application using Docker Compose. This setup provides an isolated environment for each component, making it easier to manage and deploy your application. You can further customize the configuration to suit your development and production needs.

https://medium.com/media/a8afeee8fd9b2a6f58ef534bb757d1df/href

Cheers…!

Dockerizing a MERN Stack Application: A Step-by-Step Guide was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.

​ Level Up Coding – Medium

about Infinite Loop Digital

We support businesses by identifying requirements and helping clients integrate AI seamlessly into their operations.

Gartner
Gartner Digital Workplace Summit Generative Al

GenAI sessions:

  • 4 Use Cases for Generative AI and ChatGPT in the Digital Workplace
  • How the Power of Generative AI Will Transform Knowledge Management
  • The Perils and Promises of Microsoft 365 Copilot
  • How to Be the Generative AI Champion Your CIO and Organization Need
  • How to Shift Organizational Culture Today to Embrace Generative AI Tomorrow
  • Mitigate the Risks of Generative AI by Enhancing Your Information Governance
  • Cultivate Essential Skills for Collaborating With Artificial Intelligence
  • Ask the Expert: Microsoft 365 Copilot
  • Generative AI Across Digital Workplace Markets
10 – 11 June 2024

London, U.K.