DEV Community

Sagar Medtiya
Sagar Medtiya

Posted on • Originally published at blog.sagarmedtiya.me on

πŸŽ‰Deploy MERN app to βš›οΈ Heroku with 🐳 DockerπŸš€πŸš€

image
πŸ“¦ 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.pngThis 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

πŸͺœ 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"
},

Enter fullscreen mode Exit fullscreen mode

πŸͺœ 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"))
}

Enter fullscreen mode Exit fullscreen mode

πŸͺœ Create a new Heroku app

Screenshot 2022-07-30 211225.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

πŸͺœ Docker Image deploy to heroku

Heroku supports 2 methods for deployment using Docker (list in Heroku docs):

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

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

web: npm start

Enter fullscreen mode Exit fullscreen mode

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).

#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"]

Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

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"]

Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

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!

Top comments (0)