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:

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.

docker build --tag flask-demo .

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

  1. Run the az login command to sign in to Azure.

    az login
    
  2. Run the az upgrade command to make sure your version of the Azure CLI is current.

    az upgrade
    
  3. 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.

  4. 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

  1. 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
    
  2. 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.

  3. 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 the AcrPull 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: