Dockerizing a MERN Stack Web Application

Deploying a MERN (MongoDB, Express, React, Node.js) stack application can be a challenging task, especially when it comes to managing dependencies, server configurations, and infrastructure. Docker, a popular containerization platform, can make the deployment process more straightforward and efficient. In this article, we will explore how you can use Docker to deploy a MERN stack application by providing a step-by-step guide and a sample project.

Prerequisites

Before we begin, there are a few prerequisites you should have in place:

  • A basic understanding of Docker and containerization concepts.

  • A MERN stack application that you want to deploy.

  • Docker installed on your system.

Step 1: Dockerizing the Backend (Node.js and Express)

The first step in deploying a MERN stack application is to containerize the backend. We will use a Dockerfile to define the backend image, including all necessary dependencies, configurations, and scripts.

Here's an example Dockerfile for a MERN stack backend:

Here's an example Dockerfile for a MERN stack backend:


FROM node:14

# Set working directory
WORKDIR /app

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

# Install dependencies
RUN npm install

# Copy source code
COPY . .

# Expose port 5000
EXPOSE 5000

# Start server
CMD ["npm", "start"]

This Dockerfile is straightforward. It starts from the official Node.js 14 image, sets the working directory, copies the package.json and package-lock.json files, installs dependencies, copies the source code, exposes port 5000 (which is the default port for a Node.js/Express server), and starts the server.

To build the Docker image, navigate to the backend directory in the terminal and run the following command:

docker build -t <image-name> .

Replace <image-name> with the name you want to give the image. This command will create a Docker image with the backend code and all necessary dependencies.

Step 2: Dockerizing the Frontend (React)

The next step is to containerize the frontend. The process is similar to the backend, but with a few differences. We will use a Dockerfile to define the frontend image, including all necessary dependencies, configurations, and scripts.

Here's an example Dockerfile for a MERN stack frontend:


FROM node:14

# Set working directory
WORKDIR /app

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

# Install dependencies
RUN npm install

# Copy source code
COPY . .

# Build React app
RUN npm run build

# Expose port 3000
EXPOSE 3000

# Start server
CMD ["npm", "start"]

This Dockerfile starts from the official Node.js 14 image, sets the working directory, copies the package.json and package-lock.json files, installs dependencies, copies the source code, builds the React app, exposes port 3000 (which is the default port for a React app), and starts the server.

To build the Docker image, navigate to the frontend directory in the terminal and run the following command:

docker build -t <image-name> .

Replace <image-name> with the name you want to give the image. This command will create a Docker image with the frontend code and all necessary dependencies.

Step 3: Docker Compose

Now that we have Docker images for the backend and frontend, we need to define how they should work together. We will use Docker Compose, a tool for defining and running multi-container Docker applications.

Create a new file named docker-compose.yml in the root directory of your project with the following contents:

:

version: '3'

services:
  backend:
    container_name: mern-backend
    build: ./backend
    ports:
      - "5000:5000"
    depends_on:
      - mongo
    environment:
      - MONGODB_URI=mongodb://mongo:27017/mern-stack

  frontend:
    container_name: mern-frontend
    build: ./frontend
    ports:
      - "3000:3000"
    depends_on:
      - backend
    environment:
      - REACT_APP_API_URL=http://backend:5000

This docker-compose.yml file defines two services: backend and frontend. Each service corresponds to a Docker image we created earlier.

The backend service defines the following:

  • container_name: The name of the container for the backend service.

  • build: The location of the Dockerfile for the backend service.

  • ports: Maps port 5000 in the container to port 5000 on the host machine.

  • depends_on: The name of the service that this service depends on. In our case, the backend service depends on the mongo service, which we will define later.

  • environment: Sets the environment variable MONGODB_URI to mongodb://mongo:27017/mern-stack, which is the URI for the MongoDB database.

The frontend service defines the following:

  • container_name: The name of the container for the frontend service.

  • build: The location of the Dockerfile for the frontend service.

  • ports: Maps port 3000 in the container to port 3000 on the host machine.

  • depends_on: The name of the service that this service depends on. In our case, the frontend service depends on the backend service.

  • environment: Sets the environment variable REACT_APP_API_URL to http://backend:5000, which is the URL for the backend service.

Step 4: Running the Application

Now that we have defined our services and their dependencies, we can run our MERN stack application using Docker Compose.

In the terminal, navigate to the root directory of your project and run the following command:

docker-compose up

This command will start all the services defined in the docker-compose.yml file. You should see output in the terminal showing the logs for each service.

Once the services have started, you can access your MERN stack application by opening a web browser and navigating to http://localhost:3000. You should see your frontend application running and making requests to the backend.

Conclusion

Using Docker to deploy a MERN stack application can make the deployment process more efficient and less error-prone. In this article, we have explored how to containerize the backend and frontend, define their dependencies using Docker Compose, and run the application. By following these steps and customizing them to fit your project's specific needs, you can easily deploy a MERN stack application using Docker.