DevOps Essentials

Deploy a Machine learning Application By hatem ben tayeb

Hatem Ben T  yeb

Devops Engineer @ Astrolab-agency Sousse

Opensource Guy, Automation Enthusiast, Archlinux SuperFan


  1. Introduction
  2. Devops Tools & Concepts
  3. Base Code (Python app)
  4. Setting Up Target Server
  5. Setting Up CI/CD
  6. Test the app
  7. Q/A




DevOps is the practice of operations and development engineers participating together in the entire service lifecycle, from design through the development process to production support. "The agile admin"

Tools and Concepts


Configuration As Code

Is a set of processes and practices that will save you time, increase your flexibility, and improve your system uptime

Ansible Playbooks

Infrastructure As Code

Is the management of infrastructure (networks, virtual machines, load balancers, and connection topology) in a descriptive model.


Requires us to describe and observe systems with declarative specifications that eventually form the basis of continuous everything


Getting a global visibility of your server including :

  1. Running Containers
  2. Containers CPU
  3. Containers RAM 
  4. Containers I/O 

Tools: Prometheus,docker,cAdvisor,Grafana

Code Base

(ML python application)

Application Code

The app is based on flask  that exposes those APIs:

  1. /kmeans : Words groups classification
  2. /ads : based on age and salary, did the custmer buy the product ?
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import KMeans
from sklearn.metrics import adjusted_rand_score
import json
import os
# Importing the libraries
import numpy as np
import pandas as pd
from flask import Flask,jsonify,request,render_template
app = Flask(__name__)

def main_page():
    return render_template('index.html')

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

    posted_data = request.get_json()
    true_k = posted_data['num_cluster']
    documents = posted_data['data']
    feeds = dict()
    vectorizer = TfidfVectorizer(stop_words='english')
    X = vectorizer.fit_transform(documents.split('.'))

    model = KMeans(n_clusters=true_k, init='k-means++', max_iter=100, n_init=1)

    order_centroids = model.cluster_centers_.argsort()[:, ::-1]
    terms = vectorizer.get_feature_names()
    for i in range(true_k):
        feeds.update({"cluster_"+str(i)+"": [terms[ind] for ind in order_centroids[i, :10]]})

    return jsonify(feeds)

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

    posted_data = request.get_json()
    age = int(posted_data['age'])
    salary = int(posted_data['salary'])

    new_data = [[age,salary]]

    # Importing the dataset
    dataset = pd.read_csv('Social_Network_Ads.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
    from sklearn.preprocessing import StandardScaler
    sc = StandardScaler()
    X_train = sc.fit_transform(X_train)
    X_test = sc.transform(X_test)
    new_data_pred = sc.transform(new_data)

    # Fitting SVM to the Training set
    from sklearn.svm import SVC
    classifier = SVC(kernel = 'linear', random_state = 0), y_train)

    # Predicting the Test set results
    y_pred = classifier.predict(new_data_pred)

    response = {
        "result" : str(y_pred)

    return jsonify(response)

if __name__ == '__main__':"", port=os.environ.get('PORT'))

Application Code

The landing page of the application 

It will be used to test the CI workflow

  1. Index.html must be on the templates directory
  2. assets must be on the static directory 
<!DOCTYPE html>
<title>EPI DSC</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="">
<link rel="stylesheet" href="">
body,h1 {font-family: "Raleway", sans-serif}
body, html {height: 100%}
.bgimg {
  background-image: url('/static/img.jpg');
  min-height: 100%;
  background-position: center;
  background-size: cover;

<div class="bgimg w3-display-container w3-animate-opacity w3-text-white">
  <div class="w3-display-topleft w3-padding-large w3-xlarge">
  <div class="w3-display-middle">
    <h1 class="w3-jumbo w3-animate-top">Hello EPI  :D</h1>
    <hr class="w3-border-grey" style="margin:auto;width:40%">
    <p class="w3-large w3-center"> DSC EPI Cloud Engineering Track 2020</p>




Ship the app

It's time to ship the app into an isolated container to be shippable on any Server ! 

FROM frolvlad/alpine-python-machinelearning
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . /app
CMD python


Code Repository
# Clone the project 
git clone

# Run it locally 
pip install -r requirements.txt

# Run the code 

#To build the docker image (change the  port=os.environ.get('PORT') => port=5000 (you can choose yor custom port))
docker build -t kmeans_app . 

#Run with docker 
docker run -p 5000:5000 kmeans_app

Server Setup



Heroku is a platform as a service (PaaS) that enables developers to build, run, and operate applications entirely in the cloud.

We need just 2 things :

  1. App name
  2. API key


We need the .netrc file to hold our credentials (login,password) for the :

  login <mail>
  password <apiKey>
  login <mail>
  password <apiKey>

Wrap Up

  • AppName: hello-devops-eniso
  • Url:
  • APIKey: <private>

Pipeline Setup



We need to put the apiKey and the registry url in gitlab as secrets.

go to : settings->CI/CD->variables

RegistryUrl format:{app_name}/{container_name}

It matches:      

Pipeline code

The pipeline has a single stage "development" that will deploy the container to the "hello-devops-eniso" app 

image : docker:latest

  - docker:dind

    DOCKER_DRIVER: overlay

    - devloppement

    stage : devloppement
         - echo -e " Start Building Docker image from Docker file ..  "
         - docker build -t $HEROKU_APP .
         - echo -e "\n build complete\n\n Start pushing image to ..."
         - docker login --username=_ -p $HEROKU_TOKEN
         - docker push $HEROKU_APP
         - echo -e " push complete ."
         - echo -e " Start pushing the app to the developpement server .. "
         - docker run  --rm  -e HEROKU_API_KEY=$HEROKU_TOKEN wingrunr21/alpine-heroku-cli container:release web --app hello-devops-eniso
         - echo -e " complete"


  • Build the container
  • login to heroku registry
  • Push the container
  • Release the container

Push The Code

Wait until Green :D

Test The App


From The Browser

From The Terminal

Test the /kmeans route

Test the /ads route

curl -X POST -H "Content-Type: application/json" "" -d @data.json | jq "."
curl -X POST -H "Content-Type: application/json" "" -d "{\"age\":36,\"salary\":140000}" | jq "."

For More

Check my 


Made with