Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Data API builder can be quickly deployed to Azure services like Azure Container Apps as part of your application stack. In this tutorial, you use the Azure CLI to automate common tasks when deploying Data API builder to Azure. First, you build a container image with Data API builder and store it in Azure Container Registry. You then deploy the container image to Azure Container Apps with a backing Azure SQL database. The entire tutorial authenticates to each component using managed identities.
In this tutorial, you:
- Create a managed identity with role-based access control permissions
- Deploy Azure SQL with the sample AdventureWorksLT dataset
- Stage the container image in Azure Container Registry
- Deploy Azure Container App with the Data API builder container image
If you don't have an Azure subscription, create a free account before you begin.
Prerequisites
- Azure subscription
- Azure Cloud Shell
- Azure Cloud Shell is an interactive shell environment that you can use through your browser. Use this shell and its preinstalled commands to run the code in this article, without having to install anything on your local environment. To start Azure Cloud Shell:
- Select Try It in a code or command block within this article. Selecting Try it doesn't automatically copy the code or command to Cloud Shell.
- Go to https://shell.azure.com, or select Launch Cloud Shell.
- Select Cloud Shell in the menu bar of the Azure portal (https://portal.azure.com)
- Azure Cloud Shell is an interactive shell environment that you can use through your browser. Use this shell and its preinstalled commands to run the code in this article, without having to install anything on your local environment. To start Azure Cloud Shell:
Create container app
First, create an Azure Container Apps instance with a system-assigned managed identity. This identity is eventually granted role-based access control permissions to access Azure SQL and Azure Container Registry.
Create a universal
SUFFIXvariable to use for multiple resource names later in this tutorial.let SUFFIX=$RANDOM*$RANDOMCreate a
LOCATIONvariable with an Azure region you selected to use in this tutorial.LOCATION="<azure-region>"Note
For example, if you want to deploy to the West US region, you would use this script.
LOCATION="westus"For a list of supported regions for the current subscription, use
az account list-locationsaz account list-locations --query "[].{Name:displayName,Slug:name}" --output tableFor more information, see Azure regions.
Create a variable named
RESOURCE_GROUP_NAMEwith the resource group name. For this tutorial, we recommendmsdocs-dab-*. You use this value multiple times in this tutorial.RESOURCE_GROUP_NAME="msdocs-dab$SUFFIX"Create a new resource group using
az group create.az group create \ --name $RESOURCE_GROUP_NAME \ --location $LOCATION \ --tag "source=msdocs-dab-tutorial"Create variables named
API_CONTAINER_NAMEandCONTAINER_ENV_NAMEwith uniquely generated names for your Azure Container Apps instance. You use these variables throughout the tutorial.API_CONTAINER_NAME="api$SUFFIX" CONTAINER_ENV_NAME="env$SUFFIX"Use
az containerapp env createto create a new Azure Container Apps environment.az containerapp env create \ --resource-group $RESOURCE_GROUP_NAME \ --name $CONTAINER_ENV_NAME \ --logs-destination none \ --location $LOCATIONCreate a new container app using the
mcr.microsoft.com/azure-databases/data-api-builderDAB container image and theaz containerapp createcommand. This container app runs successfully, but isn't connected to any database.az containerapp create \ --resource-group $RESOURCE_GROUP_NAME \ --environment $CONTAINER_ENV_NAME \ --name $API_CONTAINER_NAME \ --image "mcr.microsoft.com/azure-databases/data-api-builder" \ --ingress "external" \ --target-port "5000" \ --system-assignedGet the principal identifier of the managed identity using
az identity showand store the value in a variable namedMANAGED_IDENTITY_PRINCIPAL_ID.MANAGED_IDENTITY_PRINCIPAL_ID=$( \ az containerapp show \ --resource-group $RESOURCE_GROUP_NAME \ --name $API_CONTAINER_NAME \ --query "identity.principalId" \ --output "tsv" \ )Tip
You can always check the output of this command.
echo $MANAGED_IDENTITY_PRINCIPAL_ID
Assign permissions
Now, assign the system-assigned managed identity permissions to read data from Azure SQL and Azure Container Registry. Additionally, assign your identity permissions to write to Azure Container Registry.
Create a variable named
RESOURCE_GROUP_IDto store the identifier of the resource group. Get the identifier usingaz group show. You use this variable multiple times in this tutorial.RESOURCE_GROUP_ID=$( \ az group show \ --name $RESOURCE_GROUP_NAME \ --query "id" \ --output "tsv" \ )Tip
You can always check the output of this command.
echo $RESOURCE_GROUP_IDUse
az role assignment createto assign the AcrPush role to your account so you can push containers to Azure Container Registry.CURRENT_USER_PRINCIPAL_ID=$( \ az ad signed-in-user show \ --query "id" \ --output "tsv" \ ) # AcrPush az role assignment create \ --assignee $CURRENT_USER_PRINCIPAL_ID \ --role "8311e382-0749-4cb8-b61a-304f252e45ec" \ --scope $RESOURCE_GROUP_IDAssign the AcrPull role to your managed identity using
az role assignment createagain. This assignment allows the managed identity to pull container images from Azure Container Registry. The managed identity is eventually assigned to an Azure Container Apps instance.# AcrPull az role assignment create \ --assignee $MANAGED_IDENTITY_PRINCIPAL_ID \ --role "7f951dda-4ed3-4680-a7ca-43fe172d538d" \ --scope $RESOURCE_GROUP_ID
Deploy database
Next, deploy a new server and database in the Azure SQL service. The database uses the AdventureWorksLT sample dataset.
Create a variable named
SQL_SERVER_NAMEwith a uniquely generated name for your Azure SQL server instance. You use this variable later in this section.SQL_SERVER_NAME="srvr$SUFFIX"Create a new Azure SQL server resource using
az sql server create. Configure the managed identity as the admin of this server.az sql server create \ --resource-group $RESOURCE_GROUP_NAME \ --name $SQL_SERVER_NAME \ --location $LOCATION \ --enable-ad-only-auth \ --external-admin-principal-type "User" \ --external-admin-name $API_CONTAINER_NAME \ --external-admin-sid $MANAGED_IDENTITY_PRINCIPAL_IDUse
az sql server firewall-rule createto create a firewall rule to allow access from Azure services.az sql server firewall-rule create \ --resource-group $RESOURCE_GROUP_NAME \ --server $SQL_SERVER_NAME \ --name "AllowAzure" \ --start-ip-address "0.0.0.0" \ --end-ip-address "0.0.0.0"Use
az sql db createto create a database within the Azure SQL server namedadventureworks. Configure the database to use theAdventureWorksLTsample data.az sql db create \ --resource-group $RESOURCE_GROUP_NAME \ --server $SQL_SERVER_NAME \ --name "adventureworks" \ --sample-name "AdventureWorksLT"Create a variable named
SQL_CONNECTION_STRINGwith the connection string for theadventureworksdatabase in your Azure SQL server instance. Construct the connection string with the fully-qualified domain name of the server usingaz sql server show. You use this variable later in this tutorial.SQL_SERVER_ENDPOINT=$( \ az sql server show \ --resource-group $RESOURCE_GROUP_NAME \ --name $SQL_SERVER_NAME \ --query "fullyQualifiedDomainName" \ --output "tsv" \ ) SQL_CONNECTION_STRING="Server=$SQL_SERVER_ENDPOINT;Database=adventureworks;Encrypt=true;Authentication=Active Directory Default;"Tip
You can always check the output of this command.
echo $SQL_CONNECTION_STRING
Build container image
Next, build a container image using a Dockerfile. Then deploy that container image to a newly created Azure Container Registry instance.
Create a variable named
CONTAINER_REGISTRY_NAMEwith a uniquely generated name for your Azure Container Registry instance. You use this variable later in this section.CONTAINER_REGISTRY_NAME="reg$SUFFIX"Create a new Azure Container Registry instance using
az acr create.az acr create \ --resource-group $RESOURCE_GROUP_NAME \ --name $CONTAINER_REGISTRY_NAME \ --sku "Standard" \ --location $LOCATION \ --admin-enabled falseCreate a multi-stage Dockerfile named
Dockerfile. In the file, implement these steps.Use the
mcr.microsoft.com/dotnet/sdkcontainer image as the base of the build stageInstall the DAB CLI.
Create a configuration file for an SQL database connection (
mssql) using theDATABASE_CONNECTION_STRINGenvironment variable as the connection string.Create an entity named
Productmapped to theSalesLT.Producttable.Copy the configuration file to the final
mcr.microsoft.com/azure-databases/data-api-buildercontainer image.
FROM mcr.microsoft.com/dotnet/sdk:8.0-cbl-mariner2.0 AS build WORKDIR /config RUN dotnet new tool-manifest RUN dotnet tool install Microsoft.DataApiBuilder RUN dotnet tool run dab -- init --database-type "mssql" --connection-string "@env('DATABASE_CONNECTION_STRING')" RUN dotnet tool run dab -- add Product --source "SalesLT.Product" --permissions "anonymous:read" FROM mcr.microsoft.com/azure-databases/data-api-builder COPY --from=build /config /AppBuild the Dockerfile as an Azure Container Registry task using
az acr build.az acr build \ --registry $CONTAINER_REGISTRY_NAME \ --image adventureworkslt-dab:latest \ --image adventureworkslt-dab:{{.Run.ID}} \ --file Dockerfile \ .Use
az acr showto get the endpoint for the container registry and store it in a variable namedCONTAINER_REGISTRY_LOGIN_SERVER.CONTAINER_REGISTRY_LOGIN_SERVER=$( \ az acr show \ --resource-group $RESOURCE_GROUP_NAME \ --name $CONTAINER_REGISTRY_NAME \ --query "loginServer" \ --output "tsv" \ )Tip
You can always check the output of this command.
echo $CONTAINER_REGISTRY_LOGIN_SERVER
Deploy container image
Finally, update the Azure Container App with the new custom container image and credentials. Test the running application to validate its connectivity to the database.
Configure the container app to use the container registry using
az containerapp registry set.az containerapp registry set \ --resource-group $RESOURCE_GROUP_NAME \ --name $API_CONTAINER_NAME \ --server $CONTAINER_REGISTRY_LOGIN_SERVER \ --identity "system"Use
az containerapp secret setto create a secret namedconn-stringwith the Azure SQL connection string.az containerapp secret set \ --resource-group $RESOURCE_GROUP_NAME \ --name $API_CONTAINER_NAME \ --secrets conn-string="$SQL_CONNECTION_STRING"Important
This connection string doesn't include any username or passwords. The connection string uses the managed identity to access the Azure SQL database. This makes it safe to use the connection string as a secret in the host.
Update the container app with your new custom container image using
az containerapp update. Set theDATABASE_CONNECTION_STRINGenvironment variable to read from the previously createdconn-stringsecret.az containerapp update \ --resource-group $RESOURCE_GROUP_NAME \ --name $API_CONTAINER_NAME \ --image "$CONTAINER_REGISTRY_LOGIN_SERVER/adventureworkslt-dab:latest" \ --set-env-vars DATABASE_CONNECTION_STRING=secretref:conn-stringRetrieve the fully qualified domain name of the latest revision in the running container app using
az containerapp show. Store that value in a variable namedAPPLICATION_URL.APPLICATION_URL=$( \ az containerapp show \ --resource-group $RESOURCE_GROUP_NAME \ --name $API_CONTAINER_NAME \ --query "properties.latestRevisionFqdn" \ --output "tsv" \ )Tip
You can always check the output of this command.
echo $APPLICATION_URLNavigate to the URL and test the
ProductREST API.echo "https://$APPLICATION_URL/api/Product"Warning
Deployment can take up to a minute. If you are not seeing a successful response, wait and refresh your browser.
Clean up resources
When you no longer need the sample application or resources, remove the corresponding deployment and all resources.
az group delete \
--name $RESOURCE_GROUP_NAME