Deploy a containerized Flask or FastAPI web app on Azure App Service
This tutorial shows you how to deploy a Python Flask or FastAPI web app to Azure App Service using the Web App for Containers feature. Web App for Containers provides an easy on-ramp for developers to take advantage of the fully managed Azure App Service platform, but who also want a single deployable artifact containing an app and all of its dependencies. For more information about using containers in Azure, see Comparing Azure container options.
In this tutorial, you use the Docker CLI and Docker to optionally create a Docker image and test it locally. You use the Azure CLI to create a Docker image in an Azure Container Registry and deploy it to Azure App Service. The web app is configured with its system-assigned managed identity (passwordless connections) and Azure role-based access to pull the Docker image from the Azure Container Registry during deployment. You can also deploy with Visual Studio Code with the Azure Tools Extension installed.
For an example of building and creating a Docker image to run on Azure Container Apps, see Deploy a Flask or FastPI web app on Azure Container Apps.
Note
This tutorial shows creating a Docker image that can then be run on App Service. This is not required to use App Service. You can deploy code directly from a local workspace to App Service without creating a Docker image. For an example, see Quickstart: Deploy a Python (Django or Flask) web app to Azure App Service.
Prerequisites
To complete this tutorial, you need:
An Azure account where you can deploy a web app to Azure App Service and Azure Container Registry. If you don't have an Azure subscription, create a free account before you begin.
Azure CLI to create a Docker image and deploy it to App Service. And optionally, Dockerand the Docker CLI to create a Docker and test it in your local environment.
Get the sample code
In your local environment, get the code.
git clone https://github.com/Azure-Samples/msdocs-python-flask-webapp-quickstart.git
cd msdocs-python-flask-webapp-quickstart
Add Dockerfile and .dockerignore files
Add a Dockerfile to instruct Docker how to build the image. The Dockerfile specifies the use of Gunicorn, a production-level web server that forwards web requests to the Flask and FastAPI frameworks. The ENTRYPOINT and CMD commands instruct Gunicorn to handle requests for the app object.
# syntax=docker/dockerfile:1
FROM python:3.11
WORKDIR /code
COPY requirements.txt .
RUN pip3 install -r requirements.txt
COPY . .
EXPOSE 50505
ENTRYPOINT ["gunicorn", "app:app"]
50505
is used for the container port (internal) in this example, but you can use any free port.
Check the requirements.txt file to make sure it contains gunicorn
.
Flask==2.2.2
gunicorn
Werkzeug==2.2.2
Add a .dockerignore file to exclude unnecessary files from the image.
.git*
**/*.pyc
.venv/
Configure gunicorn
Gunicorn can be configured with a gunicorn.conf.py file. When the gunicorn.conf.py file is located in the same directory where gunicorn is run, you don't need to specify its location in the Dockerfile. For more information about specifying the configuration file, see Gunicorn settings.
In this tutorial, the suggested configuration file configures gunicorn to increase its number of workers based on the number of CPU cores available. For more information about gunicorn.conf.py file settings, see Gunicorn configuration.
# Gunicorn configuration file
import multiprocessing
max_requests = 1000
max_requests_jitter = 50
log_file = "-"
bind = "0.0.0.0:50505"
workers = (multiprocessing.cpu_count() * 2) + 1
threads = workers
timeout = 120
Build and run the image locally
Build the image locally.
Note
If the docker build
command returns an error, make sure the docker deamon is running. On Windows, make sure that Docker Desktop is running.
Run the image locally in a Docker container.
docker run --detach --publish 5000:50505 flask-demo
Open the http://localhost:5000
URL in your browser to see the web app running locally.
The --detach
option runs the container in the background. The --publish
option maps the container port to a port on the host. The host port (external) is first in the pair, and the container port (internal) is second. For more information, see Docker run reference.
Create a resource group and Azure Container Registry
Run the az login command to sign in to Azure.
az login
Run the az upgrade command to make sure your version of the Azure CLI is current.
az upgrade
Create a group with the az group create command.
az group create --name web-app-simple-rg --location eastus
An Azure resource group is a logical container into which Azure resources are deployed and managed. When creating a resource group, you specify a location, such as eastus.
Create an Azure Container Registry with the az acr create command.
az acr create --resource-group web-app-simple-rg \ --name webappacr123 --sku Basic
Note
The registry name must be unique in Azure. If you get an error, try a different name. Registry names can consist of 5-50 alphanumeric characters. Hyphens and underscores are not allowed. To learn more, see Azure Container Registry name rules. If you use a different name, make sure that you use your name rather than
webappacr123
in the commands that reference the registry and registry artifacts in following sections.An Azure Container Registry is a private Docker registry that stores images for use in Azure Container Instances, Azure App Service, Azure Kubernetes Service, and other services. When creating a registry, you specify a name, SKU, and resource group.
Build the image in Azure Container Registry
Build the Docker image in Azure with the az acr build command. The command uses the Dockerfile in the current directory, and pushes the image to the registry.
az acr build \
--resource-group web-app-simple-rg \
--registry webappacr123 \
--image webappsimple:latest .
The --registry
option specifies the registry name, and the --image
option specifies the image name. The image name is in the format registry.azurecr.io/repository:tag
.
Deploy web app to Azure
Create an App Service plan with the az appservice plan command.
az appservice plan create \ --name webplan \ --resource-group web-app-simple-rg \ --sku B1 \ --is-linux
Set an environment variable to your subscription ID. It's used in the
--scope
parameter in the next command.SUBSCRIPTION_ID=$(az account show --query id --output tsv)
The command for creating the environment variable is shown for the Bash shell. Change the syntax as appropriate for other environments.
Create the web app with the az webapp create command.
az webapp create \ --resource-group web-app-simple-rg \ --plan webplan --name webappsimple123 \ --assign-identity [system] \ --role AcrPull \ --scope /subscriptions/$SUBSCRIPTION_ID/resourceGroups/web-app-simple-rg \ --acr-use-identity --acr-identity [system] \ --container-image-name webappacr123.azurecr.io/webappsimple:latest
Notes:
The web app name must be unique in Azure. If you get an error, try a different name. The name can consist of alphanumeric characters and hyphens, but can't start or end with a hyphen. To learn more, see Microsoft.Web name rules.
If you're using a name different than
webappacr123
for your Azure Container Registry, make sure you update the--container-image-name
parameter appropriately.The
--assign-identity
,--role
, and--scope
parameters enable the system-assigned managed identity on the web app and assign it theAcrPull
role on the resource group. This gives the managed identity permission to pull images from any Azure Container Registry in the resource group.The
--acr-use-identity
and--acr-identity
parameters configure the web app to use its system-assigned managed identity to pull images from the Azure Container Registry.It can take a few minutes for the web app to be created. You can check the deployment logs with the az webapp log tail command. For example,
az webapp log tail --resource-group web-app-simple-rg --name webappsimple123
. If you see entries with "warmup" in them, the container is being deployed.The URL of the web app is
<web-app-name>.azurewebsites.net
, for example,https://webappsimple123.azurewebsites.net
.
Make updates and redeploy
After you make code changes, you can redeploy to App Service with the az acr build and az webapp update commands.
Clean up
All the Azure resources created in this tutorial are in the same resource group. Removing the resource group removes all resources in the resource group and is the fastest way to remove all Azure resources used for your app.
To remove resources, use the az group delete command.
az group delete --name web-app-simple-rg
You can also remove the group in the Azure portal or in Visual Studio Code and the Azure Tools Extension.
Next steps
For more information, see the following resources: