Quickstart: Deploy a Dapr application to Azure Container Apps using the Azure CLI
Dapr (Distributed Application Runtime) helps developers build resilient, reliable microservices. In this quickstart, you learn how to enable Dapr sidecars to run alongside your microservices container apps. You'll:
- Create a Container Apps environment and Azure Blog Storage state store for your container apps.
- Deploy a Python container app that publishes messages.
- Deploy a Node.js container app that subscribes to messages and persists them in a state store.
- Verify the interaction between the two microservices using the Azure portal.
This quickstart mirrors the applications you deploy in the open-source Dapr Hello World quickstart.
Setup
To sign in to Azure from the CLI, run the following command and follow the prompts to complete the authentication process.
az login
To ensure you're running the latest version of the CLI, run the upgrade command.
az upgrade
Next, install or update the Azure Container Apps extension for the CLI.
If you receive errors about missing parameters when you run az containerapp
commands in Azure CLI or cmdlets from the Az.App
module in Azure PowerShell, be sure you have the latest version of the Azure Container Apps extension installed.
az extension add --name containerapp --upgrade
Note
Starting in May 2024, Azure CLI extensions no longer enable preview features by default. To access Container Apps preview features, install the Container Apps extension with --allow-preview true
.
az extension add --name containerapp --upgrade --allow-preview true
Now that the current extension or module is installed, register the Microsoft.App
and Microsoft.OperationalInsights
namespaces.
az provider register --namespace Microsoft.App
az provider register --namespace Microsoft.OperationalInsights
Set environment variables
Set the following environment variables. Replace the <PLACEHOLDERS>
with your values:
RESOURCE_GROUP="<RESOURCE_GROUP>"
LOCATION="<LOCATION>"
CONTAINERAPPS_ENVIRONMENT="<CONTAINERAPPS_ENVIRONMENT>"
Create an Azure resource group
Create a resource group to organize the services related to your container app deployment.
az group create \
--name $RESOURCE_GROUP \
--location "$LOCATION"
Create an environment
An environment in Azure Container Apps creates a secure boundary around a group of container apps. Container Apps deployed to the same environment are deployed in the same virtual network and write logs to the same Log Analytics workspace.
To create the environment, run the following command:
az containerapp env create \
--name $CONTAINERAPPS_ENVIRONMENT \
--resource-group $RESOURCE_GROUP \
--location "$LOCATION"
Set up a state store
Create an Azure Blob Storage account
With the environment deployed, deploy an Azure Blob Storage account that is used by the Node.js container app to store data. Before deploying the service, choose a name for the storage account. Storage account names must be unique within Azure, from 3 to 24 characters in length and must contain numbers and lowercase letters only.
STORAGE_ACCOUNT_NAME="<storage account name>"
Use the following command to create the Azure Storage account.
az storage account create \
--name $STORAGE_ACCOUNT_NAME \
--resource-group $RESOURCE_GROUP \
--location "$LOCATION" \
--sku Standard_RAGRS \
--kind StorageV2
Configure a user-assigned identity for the node app
While Container Apps supports both user-assigned and system-assigned managed identity, a user-assigned identity provides the Dapr-enabled Node.js app with permissions to access the blob storage account.
Create a user-assigned identity.
az identity create --resource-group $RESOURCE_GROUP --name "nodeAppIdentity" --output json
Retrieve the
principalId
andid
properties and store in variables.PRINCIPAL_ID=$(az identity show -n "nodeAppIdentity" --resource-group $RESOURCE_GROUP --query principalId | tr -d \") IDENTITY_ID=$(az identity show -n "nodeAppIdentity" --resource-group $RESOURCE_GROUP --query id | tr -d \") CLIENT_ID=$(az identity show -n "nodeAppIdentity" --resource-group $RESOURCE_GROUP --query clientId | tr -d \")
Retrieve the subscription ID for your current subscription.
SUBSCRIPTION_ID=$(az account show --query id --output tsv)
Assign the
Storage Blob Data Contributor
role to the user-assigned identity.az role assignment create --assignee $PRINCIPAL_ID \ --role "Storage Blob Data Contributor" \ --scope "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/ Microsoft.Storage/storageAccounts/$STORAGE_ACCOUNT_NAME"
Configure the state store component
While you have multiple options for authenticating to external resources via Dapr. This example uses an Azure-based state store, so you can provide direct access from the Node.js app to the Blob store using Managed Identity.
In a text editor, create a file named statestore.yaml with the properties that you sourced from the previous steps.
# statestore.yaml for Azure Blob storage component componentType: state.azure.blobstorage version: v1 metadata: - name: accountName value: "<STORAGE_ACCOUNT_NAME>" - name: containerName value: mycontainer - name: azureClientId value: "<MANAGED_IDENTITY_CLIENT_ID>" scopes: - nodeapp
This file helps enable your Dapr app to access your state store.
Navigate to the directory in which you stored the yaml file and run the following command to configure the Dapr component in the Container Apps environment.
az containerapp env dapr-component set \ --name $CONTAINERAPPS_ENVIRONMENT --resource-group $RESOURCE_GROUP \ --dapr-component-name statestore \ --yaml statestore.yaml
Deploy the Node.js application
az containerapp create \
--name nodeapp \
--resource-group $RESOURCE_GROUP \
--user-assigned $IDENTITY_ID \
--environment $CONTAINERAPPS_ENVIRONMENT \
--image dapriosamples/hello-k8s-node:latest \
--min-replicas 1 \
--max-replicas 1 \
--enable-dapr \
--dapr-app-id nodeapp \
--dapr-app-port 3000 \
--env-vars 'APP_PORT=3000'
If you're using an Azure Container Registry, include the --registry-server <REGISTRY_NAME>.azurecr.io
flag in the command.
By default, the image is pulled from Docker Hub.
Deploy the Python application
az containerapp create \
--name pythonapp \
--resource-group $RESOURCE_GROUP \
--environment $CONTAINERAPPS_ENVIRONMENT \
--image dapriosamples/hello-k8s-python:latest \
--min-replicas 1 \
--max-replicas 1 \
--enable-dapr \
--dapr-app-id pythonapp
If you're using an Azure Container Registry, include the --registry-server <REGISTRY_NAME>.azurecr.io
flag in the command.
Verify the results
Confirm successful state persistence
You can confirm that the services are working correctly by viewing data in your Azure Storage account.
Open the Azure portal in your browser and navigate to your storage account.
Select Data Storage > Containers in the left side menu.
Select the container app.
Verify that you can see the file named
order
in the container.Select the file.
Select the Edit tab.
Select the Refresh button to observe how the data automatically updates.
View Logs
Logs from container apps are stored in the ContainerAppConsoleLogs_CL
custom table in the Log Analytics workspace. You can view logs through the Azure portal or via the CLI. There may be a small delay initially for the table to appear in the workspace.
View logs using the command line using the following CLI command.
LOG_ANALYTICS_WORKSPACE_CLIENT_ID=`az containerapp env show --name $CONTAINERAPPS_ENVIRONMENT --resource-group $RESOURCE_GROUP --query properties.appLogsConfiguration.logAnalyticsConfiguration.customerId --out tsv`
az monitor log-analytics query \
--workspace $LOG_ANALYTICS_WORKSPACE_CLIENT_ID \
--analytics-query "ContainerAppConsoleLogs_CL | where ContainerAppName_s == 'nodeapp' and (Log_s contains 'persisted' or Log_s contains 'order') | project ContainerAppName_s, Log_s, TimeGenerated | sort by TimeGenerated | take 5" \
--out table
The following output demonstrates the type of response to expect from the CLI command.
ContainerAppName_s Log_s TableName TimeGenerated
-------------------- ------------------------------- ------------- ------------------------
nodeapp Got a new order! Order ID: 61 PrimaryResult 2021-10-22T21:31:46.184Z
nodeapp Successfully persisted state. PrimaryResult 2021-10-22T21:31:46.184Z
nodeapp Got a new order! Order ID: 62 PrimaryResult 2021-10-22T22:01:57.174Z
nodeapp Successfully persisted state. PrimaryResult 2021-10-22T22:01:57.174Z
nodeapp Got a new order! Order ID: 63 PrimaryResult 2021-10-22T22:45:44.618Z
Clean up resources
Since pythonapp
continuously makes calls to nodeapp
with messages that get persisted into your configured state store, it is important to complete these cleanup steps to avoid ongoing billable operations.
If you'd like to delete the resources created as a part of this walkthrough, run the following command.
Caution
This command deletes the specified resource group and all resources contained within it. If resources outside the scope of this tutorial exist in the specified resource group, they will also be deleted.
az group delete --resource-group $RESOURCE_GROUP
Tip
Having issues? Let us know on GitHub by opening an issue in the Azure Container Apps repo.