Azure App Services is a fully managed Platform as a Service (PaaS) offering from Azure to help you build and host web applications in the cloud.
By default, Azure App Services for python is set up to use Gunicorn to deploy Flask or Django applications and, indeed, most of the docs and/or tutorials explain how to deploy Flask or Django applications.
Gunicorn is a WSGI HTTP web server but what if we wanted to deploy a Streamlit application, which doesn’t use WSGI but instead uses Tornado as its web server?
In this blog post we explore how to deploy Streamlit applications to Azure App Services using one-click deployment.
The repository and one-click deployment for this blog post can be found here.
Quick disclaimer: At the time of writing, I am currently a Microsoft Employee
The application we’ll be using is the “Time series annotations” example from Streamlit as it is a simple, one-script demonstration.
A live demo of this application can be found here.
The same script that runs this Streamlit application can be found in the
app directory of this blog post’s repository.
If you’d like to run this application locally:
- Clone the repo for this blog post
- Create a new python virtual environment
pip install -r requirements.txt
streamlit run app/streamlit_app.py
Deployment to Azure
If you wanted to run your Streamlit application in production, the best practice would be to set up a reverse proxy such as Nginx but if you just want to get up and running quickly for demonstration purposes you can serve your content directly from Streamlit and that’s what we’re going to be doing here.
As we can see from the App Services documentation for configuring python applications, Apps are run by default using the Gunicorn WSGI HTTP Server, using the additional arguments
--bind=0.0.0.0 --timeout 600.
We can also see that the priority for running a python application is:
- Use a custom startup command, if provided.
- Check for the existence of a Django app, and launch Gunicorn for it if detected.
- Check for the existence of a Flask app, and launch Gunicorn for it if detected.
- If no other app is found, start a default app that’s built into the container.
Therefore we’ll be using a custom startup command. You can provide this post deployment in the Azure Portal or as part of an Azure CLI command as explained in the documenation but we’ll be including it in our deployment template.
Something else we need to take into consideration is that a
requirements.txt file must be in the project root, so therefore we have put the requirements file in the root of our repo.
Deploying to Azure using an ARM Template
We’ll deploy our application to Azure using an Azure Resource Manager (ARM) template. ARM templates are a form of infrastructure as code, a concept where you define the infrastructure that needs to be deployed. For more information about ARM templates, see the documentation here.
The ARM template is a JSON file and we’ll use this to deploy our application. We’ll deploy our application directly from our public git repo.
This ARM template can be found here and contains a number of parameters, all of which have defaults defined:
- Web App Name
- Runtime stack
- Git Repo URL
- Git Repo branch
Note that, in our ARM template, we include a
Microsoft.Web/sites/config resource, with an
appCommandLine property, this is our custom startup command, which is:
"python -m streamlit run app/streamlit_app.py --server.port 8000 --server.address 0.0.0.0"
This runs our Streamlit app and binds to 0.0.0.0 on port 8000.
We can deploy this directly to Azure using one-click deploy, which is directed to our ARM template:
If you click on the button above, you will be taken to a page where you can deploy your application and change the parameters defined above to your needs:
Alternatively, you can use the Azure CLI to deploy the ARM template.
This can take some time to deploy as the requirements take a while to install and the streamlit application gets up and running but once it’s complete, you can navigate to your application’s URL and see your Streamlit web app up and running!