Running Python in Azure App Service

This article describes how to deploy a Python Flask app to the Azure App Service for Linux. If you’ve not tried deploying Python on App Service lately it’s worth taking a look. What I like is it’s easy to lift-and-shift a local Python web app directly into Azure in just a few steps, and keep it updated with a single command. Previous versions of web apps ran on Windows under the hood, but the new App Service preview runs Python, Java and Node apps on Linux. It’s also become more intuitive to use, and faster. Expect further improvements as it gets closer to GA.

App Service vs. web apps vs. websites – WTF is it called?

I was somewhat confused about the name at first, as the documentation sometimes refers to web apps, and older docs refer to Azure websites (and azurewebsites.net is still the domain that an app uses). Long story short, the service is called called App Service – and it’s divided into App Service (which runs on Windows), and App Service for Linux. You can find it if you search for Web Apps or App Services in the Azure portal.

For the rest of this article, which is about Python web apps, assume “App Service” means the Linux version, and that you can deploy a “web app” on it. There’s also a thing called Azure Web Apps for Containers which is part of the App Service for Linux and used for running Docker images.

Basic Ingredients

To create a Python Flask app and deploy it to Azure you need:

– An Azure subscription.

– Install Python locally. The example below assumes Python 3.7.

– Install Flask locally (pip install flask).

– Install git locally – we’ll use the git bash shell in a local git repo to push code to the App Service app once it’s created.

– Create a github repo and clone it locally. For most git tasks like this I use the GitHub Desktop. The GitHub Desktop GUI has become a lot better and I mostly prefer using it over Git command line given the choice.

Many tutorials also recommend creating a virtual environment for your local Python app. Probably a good idea, for a more complex project it helps keep track of the import libraries you need to put in your requirements.txt file (more about that later). However for a basic Flask app, I don’t see much value in creating one so didn’t bother.

Create a web app

A web app can be created with a simple set of Azure CLI  (or PowerShell) commands that you can run in the Azure cloud shell. (Cloud Shell is so useful, does anyone bother installing CLI locally anymore?)

Note: Microsoft is working on further simplifying the commands to create an App Service app, so if you see this post more than a couple of months after it was published, check the latest App Service on Linux documentation.

Here’s an example CLI script to create a web app, which includes creating a resource group, web app and a deployment user (which you’ll use to send code from your local git repo to Azure). The individual steps are explained in more detail in the Microsoft docs getting started tutorial: Create a Python app in Azure App Service on Linux (preview).

# create an admin user and password for the app
az webapp deployment user set --user-name yourusername --password yourpassword

# create an Azure resource group
az group create --name yourrgname --location westus2

# create a Linux app service plan - note the sku value - B1 is basic small, the free tier is F1
az appservice plan create --name yourappplan --resource-group yourrgname --sku B1 --is-linux

# create a web app in this resource group - the --name argument must be unique to azurewebsites.net
az webapp create --resource-group yourrgname --plan yourappplan --name yourwebapp --runtime "PYTHON|3.7" --deployment-local-git

Look at the output from the “webapp create” command and note the deploymentLocalGitUrl value. You’ll need this to configure git.

"deploymentLocalGitUrl": "https://yourusername@yourwebapp.scm.azurewebsites.net/yourwebapp.git"

Create a Flask app in a GitHub repo

First create a GitHub repo for your app, then put your Flask app in the repo. Here’s an example I used for a simple word finder/crossword solver/password generator app called “Word Finder General”.

GitHub repo: https://github.com/gbowerman/wfgeneral

If you run “python application.py” in the folder where you put the app, it will listen on 127.0.0.1:5000 and you can do your development work locally.

screenshot

The requirements requirement

Note that while the app might be running fine locally, it won’t work in the Azure App Service unless it has a valid requirements.txt file which lists which import libraries need to be installed. The simple word finder app above doesn’t have any special import requirements apart from Flask, so the requirements.txt file contains:

Flask==1.0.2

How do you initialize a Flask app?

Suppose the Flask app needs to do initialization work before it starts serving HTTP requests. Where should one put the initialization code?

Any code that needs to run in the Azure app must go within the Flask app itself. For example, though the following code would run locally, it wouldn’t run in the App Service:

if __name__ == '__main__':
    this_function_never_gets_called()
    app.run()

Therefore if your Flask app needs to do initialization, consider putting it in a function registered with @app.before_request or @app.before_first_request, E.g.

@app.before_request
def check_for_init():
    this_function_gets_called_yay()

Deploy to Azure App Service

Once the app is working well locally and you’ve synced it with the master on GitHub, it’s time to deploy it to the App Service using the deploymentLocalGitUrl value from the “webapp create” command output.

Start a git command window, cd to the folder where your local application.py is and add an Azure remote reference E.g.

git remote add azure https://yourusername@yourwebapp.scm.azurewebsites.net/yourwebapp.git

Note: For this command you’ll need the user and password you created earlier with the “az webapp deployment user set”.

Now you can deploy the app:

git push azure master

Once the command has finished running, your app should be running at yourwebapp.azurewebsites.net.

Any time you make code changes from now on, you can redeploy it to the App Service with the “git push” command. So a change process might look like:

  • Edit code locally.
  • Test locally.
  • Commit/push to GitHub master.
  • git push azure master.

Logging: How do you look at standard output?

Once the Flask app is running in App Service you can’t see the standard output by default, which would be annoying if the app gets an unhandled exception and all you can see is a 500 Server error. You can switch on logging in the Azure Portal by finding App Services, scrolling down to Diagnostic Logs and switching on Application Logging.

webapp
Now you can look at the Log stream in the portal or download the logs.

Word finder general example app

Putting this all together, the Word Finder app GitHub repo mentioned earlier, is currently running here: https://wfgeneral.azurewebsites.net/ (though may not be running by the time you read this).

Overall the process to put a Flask app into the Azure App Service for Linux is quite straightforward. Next I’m planning to look into running Docker images in App Service, and then take another look at Azure Functions.

Further reading

– The hello world tutorial in the Microsoft docs provides more detail for some of the steps described above: Create a Python app in Azure App Service on Linux (preview)

– Also look into deploying Docker images using Azure App Service for Linux: Use a Custom Docker Image for Azure Web App for Containers.

Advertisements
This entry was posted in Cloud, Computers and Internet, Linux, Python and tagged , , , , . Bookmark the permalink.

1 Response to Running Python in Azure App Service

  1. Pingback: Deploying a Docker image to the Azure App Service | MSFT Stack

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s