Deploying Machine Learning Model to Heroku with Docker and GitHub Actions

Dharmaraj
6 min readApr 21, 2023

--

Hi Scientists, In this blog we are going to explore deployment in Heroku cloud server. If you have any doubts in Model Development and Flask API please refer my previous blogs. Its important to know about Heroku, Docker, and GitHub Actions before diving into our topic.

What is Heroku?

Heroku is a container-based cloud Platform as a Service (PaaS). Developers use Heroku to deploy, manage, and scale modern apps. Our platform is elegant, flexible, and easy to use, offering developers the simplest path to getting their apps to market.

What is Docker?

Docker is a software platform that allows you to build, test, and deploy applications quickly. Docker packages software into standardized units called containers that have everything the software needs to run including libraries, system tools, code, and runtime.

What is GitHub Actions?

GitHub Actions is a continuous integration and continuous delivery (CI/CD) platform that allows you to automate your build, test, and deployment pipeline. You can create workflows that build and test every pull request to your repository, or deploy merged pull requests to production.

Model Development

To predict whether a buyer would purchase a car or not, we apply the machine learning Random Forest Classifier algorithm.

model.py

# Importing the libraries
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import confusion_matrix
from sklearn import metrics

# Importing the dataset
dataset = pd.read_csv('purhchase_data.csv')
X = dataset.iloc[:, [2, 3]].values
y = dataset.iloc[:, 4].values

# Splitting the dataset into the Training set and Test set
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.25, random_state = 0)

# Feature Scaling
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)

# Fitting Random Forest Classification to the Training set
classifier = RandomForestClassifier(n_estimators = 10, criterion = 'entropy', random_state = 0)
classifier.fit(X_train, y_train)

# Predicting the Test set results
y_pred = classifier.predict(X_test)
# Accuracy
print('Accuracy Score:', metrics.accuracy_score(y_test,y_pred))
# Confusion Matrix
print('Confusion Matrix')
print(confusion_matrix(y_test, y_pred))

Output

Prediction Test


user_age_salary=[[32,300000]]
scaled_result = sc.transform(user_age_salary)
res=classifier.predict(scaled_result)
if res==1:
print("Purchaser")
else:
print("Not a purchaser")

Output

Save Model and Scaler

#save model and Scaler
import pickle
from pickle import dump
pickle.dump(classifier, open('model.pkl','wb'))
dump(sc, open('scaler.pkl', 'wb'))

Flask Web Application for Model Deployment

index.hml

<html >
<head>
<meta charset="UTF-8">
<title>Sales Prediction</title>
</head>
<body>
<center>
<div class="login">
<h2>SALES PREDICTION</H2>
<form action="{{ url_for('predict')}}"method="post">
<input type="text" name="age" placeholder="Enter the Age" required="required" />
<input type="text" name="salary" placeholder="Enter the Salary" required="required" />
<button type="submit" class="button button2">Predict</button>
</form>
<br>
<br>
{{ prediction_text }}
</div>
</center>
</body>
</html>

app.py

import numpy as np
from flask import Flask, request, jsonify, render_template
import pickle
import json
from sklearn.preprocessing import StandardScaler
app = Flask(__name__)
model = pickle.load(open('model.pkl', 'rb'))
scaler=pickle.load(open('scaler.pkl', 'rb'))

@app.route('/')
def home():
return render_template('index.html')

@app.route('/predict',methods=['POST'])
def predict():

user_age_salary = [int(x) for x in request.form.values()]
user_age_salary1=[user_age_salary]
scaled_result = scaler.transform(user_age_salary1)
prediction = model.predict(scaled_result)
if prediction==1:
return render_template('index.html', prediction_text='Yes, Purchaser')
else:
return render_template('index.html', prediction_text='No, Not a Purchaser')


@app.route('/predict_api',methods=['POST'])
def predict_api():

data = request.get_json()
age=data['age']
salary=data['salary']
user_age_salary=[[age,salary]]
scaled_result = scaler.transform(user_age_salary)
res=model.predict(scaled_result)
if res==1:
return jsonify({'Sales Prediction': 'Yes, Purchaser' })
else:
return jsonify({'Sales Prediction': 'No, Not a Purchaser' })

if __name__ == "__main__":
app.run(debug=True,use_reloader=False)

Output

After executing these codes you will get output like the below screen.

Copy the last URL (http://127.0.0.1:5000/) and paste it into chrome or any other browser. Enter age and salary press predict button it will predict and display it on the screen.

Creating the Dockerfile

Create new file named as ‘Dockerfile’ and no need extension for this file. Copy the below code and paste into the docker file.

FROM python:3.7
COPY . /app
WORKDIR /app
RUN pip install -r requirement.txt
EXPOSE $PORT
CMD gunicorn --workers=4 --bind 0.0.0.0:$PORT app:app

Create Application in Heroku

Log into Heroku, in the dashboard, click on ‘New’ then select ‘Create new App’. In your Heroku dashboard, go to your personal settings. Find your API key, click on reveal and copy it, you’ll need it later.

GitHub Actions

Go to the Settings tab of the GitHub repository, scroll down to Secrets and add your HEROKU_EMAIL and HEROKU_API_KEY as repository secrets.

Create .yaml file

The Docker build/push-piece can be achieved using shell commands. I include the shell version here as a reference. Use below code for your project.

# Your workflow name.
name: Deploy to heroku.

# Run workflow on every push to main branch.
on:
push:
branches: [main]

# Your workflows jobs.
jobs:
build:
runs-on: ubuntu-latest
steps:
# Check-out your repository.
- name: Checkout
uses: actions/checkout@v2


### ⬇ IMPORTANT PART ⬇ ###

- name: Build, Push and Release a Docker container to Heroku. # Your custom step name
uses: gonuit/heroku-docker-deploy@v1.3.3 # GitHub action name (leave it as it is).
with:
# Below you must provide variables for your Heroku app.

# The email address associated with your Heroku account.
# If you don't want to use repository secrets (which is recommended) you can do:
# email: my.email@example.com
email: ${{ secrets.HEROKU_EMAIL }}

# Heroku API key associated with provided user's email.
# Api Key is available under your Heroku account settings.
heroku_api_key: ${{ secrets.HEROKU_API_KEY }}

# Name of the heroku application to which the build is to be sent.
heroku_app_name: ${{ secrets.HEROKU_APP_NAME }}

# (Optional, default: "./")
# Dockerfile directory.
# For example, if you have a Dockerfile in the root of your project, leave it as follows:
dockerfile_directory: ./

# (Optional, default: "Dockerfile")
# Dockerfile name.
dockerfile_name: Dockerfile

# (Optional, default: "")
# Additional options of docker build command.
docker_options: "--no-cache"

# (Optional, default: "web")
# Select the process type for which you want the docker container to be uploaded.
# By default, this argument is set to "web".
# For more information look at https://devcenter.heroku.com/articles/process-model
process_type: web



### ⬆ IMPORTANT PART ⬆ ###

Now open terminal in your IDE then use commit and push command to see the results in GitHub and Heroku. For Commit, git commit -m “Heroku commit”. For Push, git push origin main.

After done all now open your Heroku application which will be running in the new tab in your browser.

Full source code in GitHub: https://github.com/DharmarajPi/Machine-Learning-Model-Deployment-in-Heroku-using-Docker-GitHub-Actions

Congratulations !!

You have completed the Machine Learning Model Deployment !!

I hope you had enjoyed this post. Have a great day.

Have doubts? Need help? Contact me!

LinkedIn: https://www.linkedin.com/in/dharmaraj-d-1b707898

Github: https://github.com/DharmarajPi

--

--

Dharmaraj

I have worked on projects that involved Machine Learning, Deep Learning, Computer Vision, and AWS. https://www.linkedin.com/in/dharmaraj-d-1b707898/