| title | Create and deploy a Flask Python web app to Azure with managed identity |
|---|---|
| description | Use the Azure CLI to create and deploy a Flask Python web app to Azure App Service. |
| ms.devlang | python |
| ms.topic | tutorial |
| ms.date | 04/21/2023 |
| ms.custom | devx-track-python |
In this tutorial, you deploy a Python Flask code to create and deploy a web app running in Azure App Service. The web app uses managed identity (passwordless connections) to access Azure Storage and Azure Database for PostgreSQL resources.
You can configure passwordless connections to Azure services using Service Connector or you can configure them manually. This tutorial shows how to use Service Connector. For more information about passwordless connections, see [Passwordless connections for Azure services](Passwordless connections for Azure services).
This tutorial shows you how to create and deploy a Python web app using the Azure CLI. You can run the command in any environment with the CLI installed, such as your local environment or the Azure Cloud Shell.
A sample Python application using the Flask framework are available to help you follow along with this tutorial. Download or clone one of the sample applications to your local workstation.
-
Clone the sample in an Azure Cloud Shell session.
git clone https://github.com/Azure-Samples/msdocs-flask-web-app-managed-identity.git -
Navigate to the application folder.
cd msdocs-flask-web-app-managed-identity
-
Set up the environment variables needed for the tutorial and create a resource group with the az group create command.
LOCATION="eastus" RAND_ID=$RANDOM RESOURCE_GROUP_NAME="msdocs-mi-web-app" APP_SERVICE_NAME="msdocs-mi-web-$RAND_ID" DB_SERVER_NAME="msdocs-mi-postgres-$RAND_ID" ADMIN_USER="demoadmin" ADMIN_PW="ChAnG33#ThsPssWD$RAND_ID" az group create --location $LOCATION --name $RESOURCE_GROUP_NAME[!IMPORTANT] The
ADMIN_PWmust contain 8 to 128 characters from three of the following categories: English uppercase letters, English lowercase letters, numbers, and nonalphanumeric characters. When creating usernames or passwords do not use the$character. Later you create environment variables with these values where the$character has special meaning within the Linux container used to run Python apps. -
Create a PostgreSQL server with the az postgres flexible-server create command. (This and subsequent commands use the line continuation character for Bash Shell (''). Change the line continuation character for your shell if needed.)
az postgres flexible-server create \ --resource-group $RESOURCE_GROUP_NAME \ --name $DB_SERVER_NAME \ --location $LOCATION \ --admin-user $ADMIN_USER \ --admin-password $ADMIN_PW \ --sku-name Standard_D2ds_v4The sku-name is the name of the pricing tier and compute configuration. For more information, see Azure Database for PostgreSQL pricing. To list available SKUs, use
az postgres flexible-server list-skus --location $LOCATION. -
Create a database named
restaurantusing the az postgres flexible-server execute command.az postgres flexible-server execute \ --name $DB_SERVER_NAME \ --admin-user $ADMIN_USER \ --admin-password $ADMIN_PW \ --database-name postgres \ --querytext 'create database restaurant;'
-
Create an app service using the az webapp up command.
az webapp up \ --resource-group $RESOURCE_GROUP_NAME \ --name $APP_SERVICE_NAME \ --runtime PYTHON:3.9 \ --sku B1The sku defines the size (CPU, memory) and cost of the app service plan. The B1 (Basic) service plan incurs a small cost in your Azure subscription. For a full list of App Service plans, view the App Service pricing page.
-
Configure App Service to use the start.sh in the repo with the az webapp config set command.
az webapp config set \ --resource-group $RESOURCE_GROUP_NAME \ --name $APP_SERVICE_NAME \ --startup-file "start.sh"
-
Add a PostgreSQL service connector with the az webapp connection create postgres-flexible command.
az webapp connection create postgres-flexible \ --resource-group $RESOURCE_GROUP_NAME \ --name $APP_SERVICE_NAME \ --target-resource-group $RESOURCE_GROUP_NAME \ --server $DB_SERVER_NAME \ --database restaurant \ --client-type python \ --system-identity -
Add a storage service connector with the az webapp connection create storage-blob command.
This command also adds a storage account and adds the web app with role Storage Blob Data Contributor to the storage account.
STORAGE_ACCOUNT_URL=$(az webapp connection create storage-blob \ --new true \ --resource-group $RESOURCE_GROUP_NAME \ --name $APP_SERVICE_NAME \ --target-resource-group $RESOURCE_GROUP_NAME \ --client-type python \ --system-identity \ --query configurations[].value \ --output tsv) STORAGE_ACCOUNT_NAME=$(cut -d . -f1 <<< $(cut -d / -f3 <<< $STORAGE_ACCOUNT_URL))
-
Create a container called photos in the storage account with the az storage container create command.
az storage container create \ --account-name $STORAGE_ACCOUNT_NAME \ --name photos \ --public-access blob
The sample Python app uses the azure.identity package and DefaultAzureCredentialClass. The DefaultAzureCredential automatically detects that a managed identity exists for the App Service and uses it to access other Azure resources (storage and Postgres in this case). There's no need to provide storage keys, certificates, or credentials to the App Service to access these resources.
-
Browse to the deployed application at the URL
http://$APP_SERVICE_NAME.azurewebsites.net.It can take a minute or two for the app to start. If you see a default app page that isn't the default sample app page, wait a minute and refresh the browser.
-
Test the functionality of the sample app by adding a restaurant and some reviews with photos for the restaurant.
The restaurant and review information is stored in Azure Database for PostgreSQL and the photos are stored in Azure Storage. Here's an example screenshot:
:::image type="content" source="./media/python-web-app-managed-identity/example-of-review-sample-app-production-deployed-small.png" lightbox="./media/python-web-app-managed-identity/example-of-review-sample-app-production-deployed.png" alt-text="An example of the sample app showing restaurant review functionality using Azure App Service, Azure PostgreSQL Database, and Azure Storage." :::
In this tutorial, all the Azure resources were created in the same resource group. Removing the resource group removes with the az group delete command removes all resources in the resource group and is the fastest way to remove all Azure resources used for your app.
az group delete --name $RESOURCE_GROUP_NAME
You can optionally add the --no-wait argument to allow the command to return before the operation is complete.