📦 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.
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.
🪜 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
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.
🪜 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 app’s page. Under “Deploy > Deployment” , click on “Container Registry”. The steps will appear below:
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).
#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 repo’s 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 repo’s 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!