Your Python flask web application now works on your machine. Your company has a cloud-first policy, so your next step would be to publish your app on the cloud. With Python apps, you first package your app on a docker container image, push it up to a container registry and then run on any of the container platforms Azure has available for you.
Linking to my prev article: This is a technical sequel to Publish your Machine Learning Model where we created a simple Python Flask app to publish the ML model for other applications to use. This article describes how to package any Python based web application into a docker container and run it on Azure. If you want to publish the prev excercise API app to Azure, everything required can be found on the prev excercise repo.
Python, Web, Containers and Azure
Azure offers a few different ways to publish Python web apps. Without getting into details, the simplest method at the moment is to 1) stuff your app into a docker container, 2) push it up to Azure Container Registry, and then 3) run it on Azure Web App for Containers. You can include any amount of automation to the process if you like. The topic of this article is though how to get your app to production now, so we focus on only what’s actually required:
- Your application and instructions on how the app is packaged into a container (the Dockerfile). Usually a directory structure containing everything the app needs to run.
- Container registry, which is a centralized storage for your ready-to-run container images.
- Container execution platform to run your container images. You may have multiple platforms, each suitable for certain use cases or app types.
Top level workflow and the results
The image below illustrates the workflow and the artifacts during the process from a distance. You start from top left corner – your application source codes. The drawing shows the steps to first create the local container, and move along until you have your web app up and running.
Image: The minimum process and setup to run a containerized web app on Azure.
I’ve also created a tiny python flask app to use here as an example. Get the source code & contained Dockerfile with the button below:
As a prerequisite, you are expected to have basic experience on Python development, working with Azure Paas Services, Git repos and it would help if you have basic understanding on docker containers – I won’t go into details on these. For your convinience, I linked most of the topics to the article if you feel you need more information on the subjects not covered here.
Create the container image
Prerequisites: Python3, Docker and Git installed on your (preferrably linux) machine.
Clone the sample repo if you haven’t already done so. The runserver.py is a standalone flask application, which you can run with “python3 runserver.py” on your local machine. Running the app starts a http server on your localhost port 5000. Run the app locally, and make sure it works by calling with your browser:
- http://localhost:5000 – You should get a hello page as response.
- http://localhost:5000/api?input=5 – Test the sample json api function.
The directory also contains the Dockerfile, which describes the content of the image to be created. If you open the Dockerfile, you’ll find that I use python3 as the base image, pip in the required libs, copy my source codes into the container, expose the flask default port 5000 for incoming calls, and finally give the command to execute my application (with Gunicorn on top) when everything is ready.
Create (build) the docker image by running command (most likely requires “sudoing” the commands):
docker build -t pythonflaskapp .
and when the building has finished ok, run the your flask app from container using command:
docker run -p 5000:5000 pythonflaskapp
Retest with browser with the localhost urls, to see that the containerized app also works. Now you have your container built and stored in your local machine docker repository. Then head to the next step.
Upload the image to Azure Container Registry
Prerequisites: Azure Subscription (you can get free one here) + create an Azure Container Registry from Azure portal. You’ll also need Azure CLI (command line interface) installed to your workstation.
Now that you have your container image ready, next step is to move the image from your local workstation to Azure Container Registry (ACR), from where it can be deployed on various container execution platforms. The full instructions on how to push the local image to ACR can be found on this page.
The process in short:
- Tag your local image to be pushed to ACR with: docker tag pythonflaskapp [myAcrName].azurecr.io/pythonflaskapp:v1
- Login to Azure ACR with: az acr login –name [MyAcrName] and follow instructions
- Push the image to ACR with: docker push [myAcrName].azurecr.io/pythonflaskapp:v1
The result is the tagged docker image copied to Azure Container Registry. You can verify that the image now is in Azure from the Azure Container Registry portal page.
I’ve created helper scripts for you in the scripts – subdir, so you don’t need to remember those commandline params…
Run Containers on Azure
The last step is to set up the container excution environment, and deploy your image. The thing that people both love and hate about Azure, is that – again – you have multiple options on how to run containers. Which one should I choose? You main options are:
- Create a virtual machine & run docker there (You don’t want this. Nobody wants this.)
- Azure Container Instance (ACI) is a PaaS service to run any single container on one compute instance. Select machine type (processor, memory) you need, and just run the container. Does not scale. (For web apps, you don’t want this either).
- Azure Web App for Containers: A Web App is a PaaS service specially designed to run web applications. Choose the machine type you need (processor, memory), and decide if you let the service scale automatically to multiple instances. Offers one click authentication for webapps. Finally: Select which container image you want to run, and should the web app autodeploy, if new images appear on the registry. This is what you want!
- Azure Container Service (AKS): A full managed kubernetes cluster for you to deploy your containers. You need lots of containerized apps running on same environment to benefit from this. An overkill in most situations.
- Create a RedHat OpenShift virtual machine cluster on Azure and run containers there. Some like the platform, so who am I to argue. But like the AKS, even bigger overkill for most use cases.
To put simply, for web apps my recommendation usually is:
Azure Web App for Containers
If new to Azure and Web Apps, watch this excellent (and quite fresh) introduction video on Azure Web Apps!
For this use case, our choice is Azure Web App for Containers. It gives you easy authentication if you need, autoscaling (no need to worry about the load balancers or stuff), and a nice autodeploy feature when new image becomes available in ACR you most likely want to have. You can also have your own domain name, SSL cert – everything.
To create the resource, go to the azure portal, and create new resource: Web App for Containers. Creating a Web App for Containers requires the following parameters:
- Give the application a name (this will also be the url address of your app). The name must be globally unique, as it will become [appname].azurewebsites.net – kind of url.
- Select the subscription you want to use (you most likely have only one).
- Create new resource group. Resource group is a folder in azure where all resources are put.
- Select or create new app service plan, see below
- Select the container you want to run on this web app. It’s the one you previously just deployed to ACR.
Image: Web App for Container settings when you are ready to create
The App Service plan and pricing tier
This is a good place to explain a little. App service plan defines on which kind of compute resource your app will be run, and where it will be run. Basically you are choosing between computer types (memory, cores), and features you need scaling etc. And of course price. For this excercise:
- create a new app service plan (give it a name too)
- closest to your location (in Finland, the closest is West Europe (Amsterdam).
- Select pricing tier B1 from Dev/Test section, it will give you also an estimate on the cost.
- Hit Apply.
Image: App Service Plan & Pricing Tier
The last step is to select the image you pushed previously to Azure Container Registry. Select your registry, image and version from the dropdowns. Leave the startup file box empty.
If you don’t see your registry listed on the dropbox, there’s a little quirk you need to know: Go to your ACR settings and enable “Admin User” setting on Azure Container Registry – Acceess keys page. See the image below. After this, your registry will appear on the list.
Image: Enable admin user for your ACR.
Now you are ready, hit Create. Azure starts creating your web app. When you first time do this, don’t be surprised – it will take like 15 minutes, sometimes even more. The little bell icon on the top bar will notify you your web app is done, but for Web App for Containers, the app deployment is still most likely in progress. Patience!
Test your app
Your app url is shown in the web app Overview section. Open your browser. This time, forget the port 5000 – Azure switched your app automatically to run on normal web ports 80 for http and 443 for https. So now, to call your app, use:
- https://[yourappname].azurewebsites.net — gives you the hello page.
- https://[yourappname].azurewebsites.net/api?input=5 — gives you api response.
As said, the deployment takes a (long) while. But in the end: Your containerized Python Flask app is now running on Azure.
The topic was the simplest path to publish Python app on Azure. I kind of pre-decided for you that putting your app on a container and run it from there is the simplest way to get thing done. Just to mention the options, you can als run python app “raw” on a web app – meaning you don’t have put it inside a container. And here are the instructions for that if you like this approach. The difference between the methods is where you want to take the fight on how to introduce the required libraries to the runtime environment (eg. tensorflow and even numpy can sometimes be a real pain to get to work on deployments). I prefer to have this fight when creating the container instance, and the rest goes easily. But that is just my taste.
As for devops, I’d at least suggest that you turn on the “Continuous Deployment” option on Web App for Containers. This option becomes available for you after you have successfully deployed the app. You can find it in your Web App – Container Settings page. There’s now an on/off switch: Turn it on and whenever you deploy a new version of your app to container registry, the web app takes the new image and redeploys it automatically. Quite simple.
If you want to take automatic build and deployment a little further, check the DevOps Project. It works perfectly with Python flask apps. In my opinion, DevOps project is an easy introduction to what’s possible to get done with the Azure DevOps toolstack.
If your app requires authetication, go to Web App – Authentication / Authorization page, and start by flicking the switch “On” to see your options. Read the Web App documentation for more details on this.
And if you need to scale to multiple instances when the load gets high, you are looking for the Web App – Scale Out (App Service) page. Enable the autoscaling (off by default), and set the rules on how you let your app to scale.
But now: Enjoy your flask app running on Azure!
- 5.6.2019 Change in Dockerfile: Added Gunicorn on top of the sample flask app. Gunicorn handles the request queuing and running your app on parallel inside the WebApp for Containers. Flask is never intended to run in production without something handling the queuing and parallelization.
- 5.6.2019 Change in runserver.py: Switched from Print() statements to app.logger. More correct approach than using print.
- 5.6.2019 Added new subfolder scripts to help you with docker build and moving the image to ACR.