🎉Deploy MERN app to ⚛️ Heroku with 🐳 Docker🚀🚀
Published: 2022-09-12 18:52:46

---
title: 🎉Deploy MERN app to ⚛️ Heroku with 🐳 Docker🚀🚀
published: true
date: 2022-07-30 18:04:58 UTC
tags: 
canonical_url: https://blog.sagarmedtiya.me/deploy-mern-app-to-heroku-with-docker
---
![image](https://cdn.hashnode.com/res/hashnode/image/upload/v1658917242522/ByxTQ65Eb.png)
📦 A container is a standard unit of software that packages up code and all its dependencies so the application runs quickly and reliably from one computing environment to another. Containerizing with Docker is now common part of app deployment. This approach eliminates missing dependencies and aids in maintenance especially when an app consists of many microservices.

We will create a 🐳 Docker image of **React + expressJs** then deploy it to **heroku**.

## 🪜 Create the basic React + expressJs app

_The 📂folder structure is as follows._

![Screenshot 2022-07-27 185423.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1658928270176/32wflbIJO.png)This is the folder structure which we will deploy it on heroku using Docker. Copy the **frontend** folder and paste it to **backend** folder.

## 🪜 Proxy

Remove the proxy from _/backend/frontend/package.json_ file, if you have any.

## 🪜 PORT 🔢number

We need to change the PORT number from Static to Dynamic for Heroku in server.js file of backend. So, heroku can sets its own PORT number through dotenv file.

![Screenshot 2022-07-30 204516.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1659194127623/TVlUtYs_Q.png)

## 🪜 Script section of package.js

Next, we need to add few 📜scripts on package.js file of backend folder to tell heroku what to do.

```
scripts: {
    start: node server.js,
    "heroku-postbuild": "NPM_CONFIG_PRODUCTION=false npm install --prefix frontend && npm run build --prefix frontend",
    test: echo \Error: no test specified\ && exit 1"
},

```

## 🪜 Serve the static files

We need to go to the frontend 📂folder and run **npm build**. It will create a build folder and that is the folder which we want to serve on Heroku as a frontend. Now we need to tell backend which files to serve. So, go to the server.js and add few lines above the app.listen() method.

```
if(process.env.NODE_ENV==="production"){
    app.use(express.static("frontend/build"))
}

```

## 🪜 Create a new Heroku app

![Screenshot 2022-07-30 211225.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1659195757651/Whojjz-yS.png)

Log in to your Heroku account. From the Dashboard, go to New > Create new app.

After choosing an App Name and Region, click Create app. Once the app is created, move to the Settings tab and note the Heroku git URL. This will be used later to deploy the Docker container.

![Screenshot 2022-07-30 211541.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1659196072293/9wLBCO-SV.png)

## 🪜 Docker Image deploy to heroku

Heroku supports 2 methods for deployment using Docker ([list in Heroku docs](https://devcenter.heroku.com/categories/deploying-with-docker)):

### a) Using 📦Container Registry

This method pushes Docker images built on your local machine to Heroku. To see the exact steps, go to your Heroku apps page. Under Deploy > Deployment , click on Container Registry. The steps will appear below:

![Screenshot 2022-07-30 220016.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1659198702420/g1QkD-tfA.png)

Create a Procfile in the root directory. Copy the following line in Procfile

```
web: npm start

```

In the backend folder, create a "DockerFile.web" file. web is the name of the process. This is the example code here. The resulting image runs on an official Nodejs image ([Check Docker Hub for versions](https://hub.docker.com/_/node/)).

```
#Start from the pre-existing official Node image
FROM node:14

# Working directory. "/usr/local/bin/" is what Heroku takes as the "root" folder. Files MUST be added here or they cannot be found!
WORKDIR /usr/local/bin/backend

#Copy the app's source code into the image's filesystem
COPY . /usr/local/bin/backend/

#Install the required dependency of expressJs. Runs in container root directory.
RUN npm install

#Install the required files for the react-app in the frontend folder
RUN npm install --prefix frontend

#Build React app
RUN npm run --prefix frontend build

#Run the app when container launches.
CMD ["npm", "start"]

```

In the same backend folder create **.dockerignore** file then insert the 👩💻code below. The Dockerfile has instructions to install the dependencies listed in backend/package.json and backend/frontend/package.json so there is no need to package the large node\_modules folders.

```
node_modules
client/node_modules

```

Now, `git add .` and `git commit -a` these new files to your local Git repo.

It is now time to upload to Heroku. Open a console in the root directory then run the following:

**1.** `$ heroku git:remote -a <herokuAppName>` Adds the Heroku Git URL to your repos remote.

**2.** `$ heroku login` Starts a prompt to enter your Heroku credentials to log into the CLI.

**3.** `heroku container:login` Logs you into the Container Registry.

**4.** `heroku container:push --recursive -a <herokuAppName>` Starts the image build process. recursive looks in every subfolder of root to find a Dockerfile.xxx. -a specifies the name of the Heroku app in your account.

**5.** `heroku container:release -a <herokuAppName> web` Releases the completed image to your Heroku app.

Congrats your app is successfully hosted. 🎉🎉

### b) Deploying using heroku.yml🎈

Let, move to the second method. create a heroku.yml file in the root directory and paste the following code:

```
build:
  docker:
    web: backend/Dockerfile

```

There is no need to create Procfile here. Create a 🐳 Dockerfile then insert the code below. Note, the name of the file is "DockerFile" not "DockerFile.web". This is because the path to the Dockerfile is specified in heroku.yml.

```
#Start from the pre-existing official Node image
FROM node:14

# Working directory. "/usr/local/bin/" is what Heroku takes as the "root" folder. Files MUST be added here or they cannot be found!
WORKDIR /usr/local/bin/backend

#Copy the app's source code into the image's filesystem
COPY . /usr/local/bin/backend/

#Install the required dependency of expressJs. Runs in container root directory.
RUN npm install

#Install the required files for the react-app in the frontend folder
RUN npm install --prefix frontend

#Build React app
RUN npm run --prefix frontend build

#Run the app when container launches.
CMD ["npm", "start"]

```

Again, in the same backend folder create **.dockerignore** file then insert the 👩💻code below. The Dockerfile has instructions to install the dependencies listed in backend/package.json and backend/frontend/package.json so there is no need to package the large node\_modules folders.

```
node_modules
client/node_modules

```

Now, `git add .` and `git commit -a` these new files to your local Git repo.

It is now time to upload to Heroku. Open a console in the root directory then run the following:

**1.** `$ heroku git:remote -a <herokuAppName>` Adds the Heroku Git URL to your repos remote.

**2.** `$ heroku login` Starts a prompt to enter your Heroku credentials to log into the CLI.

**3.** `heroku container:login` Logs you into the Container Registry.

**4.** `heroku container:push --recursive -a <herokuAppName>` Starts the image build process. recursive looks in every subfolder of root to find a Dockerfile.xxx. -a specifies the name of the Heroku app in your account.

**5.** `heroku container:release -a <herokuAppName> web` Releases the completed image to your Heroku app.

Congrats your app is successfully hosted. 🎉🎉

Thanks for reading!