Deploy Python Flask app in Azure VM using Azure DevOps Organization Pipeline

Sabir Piludiya
10 min readMar 29, 2021

In this Tutorial, We will discuss regarding the deployment of Python Flask application in Azure Virtual Machine with CI/CD using Azure DevOps Pipeline. Also, we will make use of Nginx as a Reverse Proxy.


  1. An account on Microsoft Azure and Azure DevOps Organization. If you don’t have one check below:
  • If you are a working professional, sign-up here
  • If you are a student, sign-up here

2. Github Account

3. Basic knowledge about Python Flask and Git.


After completing the tutorial you will be able to

  • Get hands-on experience with how to use Microsoft Azure Virtual Machine for deploying services in integration with Python.
  • You will get hands-on practice with DevOps Organization Pipelines for automating deployment.
  • You will have a Python Flask application ready for showcasing.

Creating Virtual Machine :

Azure Virtual Machine (VM) is one of several types of on-demand, scalable computing resources that Azure offers. Typically, you choose a VM when you need more control over the computing environment than the other choices offer. We are going to use the VM for deploying our Python application.

In order to create the Virtual Machine in Azure, go through the following steps :

Go to the Virtual Machine section in Azure and select Add Virtual Machine.

Create Azure Virtual Machine

We will use here Ubuntu VM with Standard B2s size to deploy our Python application. Let’s provide an appropriate name to the VM and Proceed to Review + create as we don’t want to change further configurations.

Specify Name, Size etc . in Azure Virtual Machine Creation

We can review the configuration on the next page. Click on Create to make VM available.

Review before Azure Virtual Machine Creation

On the next screen, We can see our deployment is complete and Virtual Machine is ready to use.

Azure Virtual Machine Deployed Screen

Don’t forget to download the key which will be used to SSH into our newly created fresh Virtual Machine.

Deploy App Manually to Test :

Now, Let’s enter into our Virtual Machine through the key which was downloaded earlier. We here create the directory to keep our code from Github and run the application from the specific location.

SSH to Azure VM

We will clone our Github repo where we have committed the code at the specified location. Also, We need to create a virtual environment to run our application.

Manually Run Python App

Let’s run and test out the Python Flask application manually from the specified location as of now, using the following commands :

python3 -m venv envsource env/bin/activatepip3 install -r requirements.txtexport FLASK_APP=run.pypython

Our application should be running.

Python App is running

As you can see, It is running on 5000 port within our Virtual Machine. We want to verify our application is actually running or not, Right?

Initially, 5000 port is not openly accessible. Let’s configure Port rules and add the 5000 port to be accessible from anywhere.

Go to the Virtual Machine and select Networking under the Settings option. Click on Add inbound port rule and specify 5000 port there.

You can see the inbound port list after updating.

Inbound Port Rule for port 5000

It’s time to verify if the Python application is actually running. Let’s hit the public IP of virtual machine with the 5000 port.



Voila.! Our Python application is running.

Application is Deployed Manually

We don’t want to manually pull and run the Python application every time we make changes to our code. Now, it’s time to automate the deployment.

Azure DevOps Organization is there to take care of such automation.

Creating Pipeline in Azure DevOps Organization :

With an organization, you gain access to the platform in which you can do the following tasks:

  • Collaborate with others to develop applications by using cloud service
  • Set up continuous integration and deployment
  • Obtain additional features and extensions

Azure Pipelines is used to build, test, and deploy in any language, to any cloud — or on-premises. Run in parallel on Linux, macOS, and Windows, and deploy containers to individual hosts or Kubernetes.

We will create the pipeline to deploy the application into the Virtual Machine on each new commit to the Github repo.

Go to the DevOps Organization and create a project.

In order to connect to the VM using the pipeline, we have to create a new service connection.

Go to the specific project on which we’re going to create a pipeline.

Select Project Settings > Service Connection

Now, Click on the New service connection button.

As we want to add a service connection to SSH into the VM, we will select SSH as the service connection type.

Create Service Connection

Here we need to provide some information of the Virtual Machine as described below :

Connection Name: Required. The name you will use to refer to this service connection in task properties.

Host name: Required. The name of the remote host machine or the IP address.

Port number: Required. The port number of the remote host machine to which you want to connect. The default is port 22.

User name: Required. The username to use when connecting to the remote host machine.

Password or passphrase: The password or passphrase for the specified username if using a keypair as credentials.

Private key: The entire contents of the private key file if using this type of authentication.

SSH Service Connection informations

Enter the required information and click on the Save button. The Service connection should be created.

It’s time to create the pipeline within our DevOps Organization Project.

Go to the new project which we are using to setup the pipeline, and click on Pipeline.

As there’s no pipeline set and available, Azure will suggest creating the first pipeline for that project.

Click on the Create Pipeline button.

Create Azure DevOps Organization Pipeline

Click on Use the classic editor as We will use the classic editor to setup our pipeline.

Create Azure DevOps Organization Pipeline — Classic Editor

Now, click on Github and select the repository and branch where we commit our code for the Python Flask application. Click on the Continue button.

Create Azure DevOps Organization Pipeline — Specify Github Repo

Now, click on Empty job as we are going to add tasks manually.

Create Azure DevOps Organization Pipeline — Select Empty Job

We want to automate the deployment using SSH. Click on the ‘+’ icon and search SSH on the tasks. Add the SSH task to the pipeline by clicking on Add button.

Create Azure DevOps Organization Pipeline — Add SSH Task

Now we need to specify a few information like the following:

Display name: The name of SSH task which will be displayed

Service Connection: Connection name which will used to connect to VM

Run: Choose to run either shell commands or a shell script on the remote machine.

Here, we have selected the Service connection which we have recently created to connect to our Python App VM. Also, we are using the Inline Script option.

We will create the shell script in the Virtual Machine which will be invoked during the trigger event of pipeline. Enter the script as below:

cd /home/azureuser/python-app;ls;./
Create Azure DevOps Organization Pipeline — SSH Task informations

Scroll down and check to Enable interactive session.

Now, Click on Triggers and check to the Enable continuous integration.

Create Azure DevOps Organization Pipeline — Select to Run on each new commit

Now click on Save & queue and just select Save.

Shell script for automating :

We are going to create the shell script which will be invoked by the Pipeline after each commit to the Github repo. We will use PM2 to keep our application running.

Installing PM2 for running app in the background:

PM2 depends on Node.js. To install Node it’s pretty straightforward:

curl -sL | sudo -E bash -
sudo apt-get install -y nodejs

Now to install PM2 type:

sudo npm install pm2 -g

Now check PM2 version using:

pm2 -v

Creating shell script:

We just create the shell script at the location /home/azureuser/python-app specified at Azure DevOps Organization pipeline.

cd /home/azureuser/python-app
sudo nano

paste following content:

##!/bin/bashcd /home/azureuser/python-app/App_VirusForecaster
git pull && echo "pull completed"
sleep 2s
source /home/azureuser/python-app/App_VirusForecaster/env/bin/activate
echo "Killing service . . ."
sudo fuser -n tcp -k 5000
sudo fuser -n tcp -k 5000
sudo fuser -n tcp -k 5000
sudo fuser -n tcp -k 5000
sudo fuser -n tcp -k 5000
pm2 stop
sleep 5s
echo "restarting service . . ."
pm2 start
echo "Deployment done...Thanks!"

Now press Ctrl+x, then hit y and enter, to save content in the file.

Run the following command to make script executable:

sudo chmod +x

Alright.! We won’t execute this script. It will be automatically invoked from the pipeline after each commit, then it pulls the new changes from the Github repo and deploys them.

Now Let’s move forward to use Nginx as a reverse proxy.

Setup and Configure Nginx as a reverse proxy :

An Nginx reverse proxy is an intermediary proxy service that takes a client request, passes it on to servers, and subsequently delivers the server’s response back to the client.

Before setting up Nginx in our Virtual Machine, let’s create a DNS name for the VM.

Go to the Virtual Machine Overview and click on Configure next to the DNS name.

Configure Azure VM DNS

Give the appropriate name for the DNS for our VM and click on Save.

Choosing Azure VM DNS

Great.! We have created the DNS name which will be used to interact with our application.

However, our application is not running on port 80, Right? It’s actually running on the 5000. Let’s use Nginx now.!!

SSH into the Virtual Machine and run following commands :

sudo apt update
sudo apt install nginx -y

Nginx should be installed. Now go to the location /etc/nginx/sites-available.

cd /etc/nginx/sites-available

Run the command nano default to edit the configuration file and paste the following block appropriately after removing by default location block. Don’t forget to replace DNS name of the Virtual Machine next to the server_name.

server_name {DNS_NAME_OF_VM}
location / {
proxy_pass http://localhost:5000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection ‘upgrade’;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;

Restart Nginx using the following command to change the configuration.

sudo systemctl restart nginx.service

Before accessing the DNS, we have to add the Port Rule to Virtual Machine. Let’s add port 80 to the list.

Inbound Port Rule for port 80

Our app should be now accessible from the DNS of the Virtual Machine. Let’s visit the DNS address. Yay.!!!

Application Running on the DNS

Testing the CI/CD pipeline :

We are done with all the setup and configurations required for Continues Integration and Continues Deployment. As we are using the Github repository, We will make the changes on our code there to test the pipeline.

Let’s change name of the application and merge that changes to the master branch which was used in the pipeline. By now, Changes is merged to master branch, it should trigger our pipeline with new commit hash.

Merge New Commit to master branch

Here, we can see the pipeline is triggered and our task is running. Amazing!

Pipeline is Triggered Automatically

Our pipeline is successfully completed and deployed new changes of the Python Flask application to Virtual Machine.

Build results of the Job

Let’s verify the changes by Visiting the DNS of the VM.

New Changes are affected to the Application

Great.!! The Application name is changed. Our changes in the Github are affected and live now.

Happy automating.!


I demonstrated how to create an Virtual Machine in Azure. Also, a pipeline in the Azure DevOps Organization was created. Then we manually deployed Python Flask application into the Virtual Machine. With the help of PM2 and shell script we deploy the application on each new commit. Finally, we used Nginx as a reverse proxy and tested our new deployment which triggered automatically using the DevOps Organization Pipeline. This article must have given you a little peek into it and help you get started today!!


Questions? Comments? Feel free to leave your feedback in the comments section or contact me directly at

Thanks for your precious time, Hope you like it.
Don’t forget to 👏 if you enjoyed this article .



Sabir Piludiya

DevOps Engineer. I am fond of learning new technologies and focusing on K8s, Automation, and Data Analytics. Contact at