Proposed Pull Request Change

title titleSuffix description author ms.author ms.service ms.custom ms.topic ms.date zone_pivot_group_filename zone_pivot_groups
Tutorial: Use Dapr Publish and Subscribe for Microservices Communication Azure Container Apps Find out how to create a publisher/subscriber system that uses the Dapr pub/sub API to communicate. Follow steps for deploying the app to Azure Container Apps. hhunter-ms hannahhunter azure-container-apps devx-track-dotnet, devx-track-js, devx-track-python how-to 12/04/2025 container-apps/dapr-zone-pivot-groups.json dapr-languages-set
📄 Document Links
GitHub View on GitHub Microsoft Learn View on Microsoft Learn
Raw New Markdown
Generating updated version of doc...
Rendered New Markdown
Generating updated version of doc...
+0 -0
+0 -0
--- title: "Tutorial: Use Dapr Publish and Subscribe for Microservices Communication" titleSuffix: "Azure Container Apps" description: Find out how to create a publisher/subscriber system that uses the Dapr pub/sub API to communicate. Follow steps for deploying the app to Azure Container Apps. author: hhunter-ms ms.author: hannahhunter ms.service: azure-container-apps ms.custom: devx-track-dotnet, devx-track-js, devx-track-python ms.topic: how-to ms.date: 12/04/2025 zone_pivot_group_filename: container-apps/dapr-zone-pivot-groups.json zone_pivot_groups: dapr-languages-set # customer intent: As a developer, I want to find out how to use the Dapr pub/sub API in my publisher and subscriber microservices so that I can streamline and standardize communication. --- # Tutorial: Use Dapr publish and subscribe for microservices communication In a publish/subscribe (pub/sub) system, you can use [Distributed Application Runtime (Dapr)](./dapr-overview.md#supported-dapr-apis-components-and-tooling) to streamline and standardize the communication between your microservices and the message broker. - The publisher app publishes messages via a Dapr sidecar. The sidecar handles the actual communication with the broker. - The subscriber app receives messages via a Dapr sidecar. The sidecar receives messages from the broker and invokes the subscriber app's endpoint with the message payload. This tutorial uses a sample project to show you how to run a Dapr pub/sub system. The sample includes: - A message generator `checkout` service (the publisher) that generates messages of a specific topic. - An `order-processor` service (the subscriber) that listens for messages from the `checkout` service of a specific topic. :::image type="content" source="media/microservices-dapr-azd/pubsub-quickstart.png" alt-text="Diagram that shows the message flow from a checkout app to a service bus via Dapr, and from the service bus to an order-processor app via Dapr."::: In this tutorial, you: > [!div class="checklist"] > * Create a publisher microservice and a subscriber microservice that use the [Dapr pub/sub API](https://docs.dapr.io/developing-applications/building-blocks/pubsub/pubsub-overview/) to send and receive messages for event-driven architectures. > * Deploy the application to Azure Container Apps by using the Azure Developer CLI and Bicep files provided in the sample project. ## Prerequisites - The [Azure Developer CLI](/azure/developer/azure-developer-cli/install-azd) - The Dapr CLI, [installed](https://docs.dapr.io/getting-started/install-dapr-cli/) and [initialized](https://docs.dapr.io/getting-started/install-dapr-selfhost/) - [Docker Desktop](https://www.docker.com/products/docker-desktop/) - [Git](https://git-scm.com/install/) ::: zone pivot="nodejs" ## Run the Node.js applications locally Before you deploy the application to Container Apps, take the steps in the following sections to run the `order-processor` and `checkout` services locally with Dapr and Azure Service Bus. ### Prepare the project 1. Clone the [sample application](https://github.com/Azure-Samples/pubsub-dapr-nodejs-servicebus) to your local machine. ```bash git clone https://github.com/Azure-Samples/pubsub-dapr-nodejs-servicebus.git ``` 1. Go to the sample root directory. ```bash cd pubsub-dapr-nodejs-servicebus ``` ### Run the applications by using the Dapr CLI Take the following steps to run the `order-processor` subscriber service and the `checkout` publisher service. 1. From the sample root directory, go to the *order-processor* directory. ```bash cd order-processor ``` 1. Install the dependencies. ```bash npm install ``` 1. Run the `order-processor` service. ```bash dapr run --app-port 5001 --app-id order-processing --app-protocol http --dapr-http-port 3501 --resources-path ../components -- npm run start ``` 1. In a new terminal window, go to the sample root directory, and then go to the *checkout* directory. ```bash cd checkout ``` 1. Install the dependencies. ```bash npm install ``` 1. Run the `checkout` service. ```bash dapr run --app-id checkout --app-protocol http --resources-path ../components -- npm run start ``` #### Expected output In the `checkout` terminal, the `checkout` service publishes 20 messages and then temporarily pauses. ``` == APP == Published data: {"orderId":1} == APP == Published data: {"orderId":2} == APP == Published data: {"orderId":3} == APP == Published data: {"orderId":4} == APP == Published data: {"orderId":5} == APP == Published data: {"orderId":6} == APP == Published data: {"orderId":7} == APP == Published data: {"orderId":8} == APP == Published data: {"orderId":9} == APP == Published data: {"orderId":10} == APP == Published data: {"orderId":11} == APP == Published data: {"orderId":12} == APP == Published data: {"orderId":13} == APP == Published data: {"orderId":14} == APP == Published data: {"orderId":15} == APP == Published data: {"orderId":16} == APP == Published data: {"orderId":17} == APP == Published data: {"orderId":18} == APP == Published data: {"orderId":19} == APP == Published data: {"orderId":20} ``` In the `order-processor` terminal, the `order-processor` service receives 20 messages. ``` == APP == Subscriber received: {"orderId":1} == APP == Subscriber received: {"orderId":2} == APP == Subscriber received: {"orderId":3} == APP == Subscriber received: {"orderId":4} == APP == Subscriber received: {"orderId":5} == APP == Subscriber received: {"orderId":6} == APP == Subscriber received: {"orderId":7} == APP == Subscriber received: {"orderId":8} == APP == Subscriber received: {"orderId":9} == APP == Subscriber received: {"orderId":10} == APP == Subscriber received: {"orderId":11} == APP == Subscriber received: {"orderId":12} == APP == Subscriber received: {"orderId":13} == APP == Subscriber received: {"orderId":14} == APP == Subscriber received: {"orderId":15} == APP == Subscriber received: {"orderId":16} == APP == Subscriber received: {"orderId":17} == APP == Subscriber received: {"orderId":18} == APP == Subscriber received: {"orderId":19} == APP == Subscriber received: {"orderId":20} ``` ### Stop the applications To stop the applications, open a separate terminal and run the following commands: ```sh dapr stop --app-id checkout dapr stop --app-id order-processor ``` ## Deploy the application template by using the Azure Developer CLI To deploy the application to Container Apps by using [`azd`](/azure/developer/azure-developer-cli/overview) commands, take the steps in the following sections. ### Prepare the project In a new terminal window, go to the [sample](https://github.com/Azure-Samples/pubsub-dapr-nodejs-servicebus) root directory. ```bash cd pubsub-dapr-nodejs-servicebus ``` ### Create and deploy by using the Azure Developer CLI 1. Run `azd init` to initialize the project. ```azdeveloper azd init ``` When prompted in the terminal, enter a unique environment name. The command uses this name as a prefix for the resource group that it creates to hold all Azure resources. 1. Run `azd up` to prepare the infrastructure and deploy the application to Container Apps in a single command. ```azdeveloper azd up ``` When prompted in the terminal, enter values for the following parameters: | Parameter | Description | | --------- | ----------- | | Azure subscription | The Azure subscription for your resources | | Azure location | The Azure location for your resources | This process can take some time to finish. While the `azd up` command runs, the output displays two Azure portal links that you can use to monitor the deployment progress. The output also demonstrates how `azd up`: - Creates and configures all necessary Azure resources via the Bicep files in the *./infra* directory by using `azd provision`. After the Azure Developer CLI deploys these resources, you can use the Azure portal to access them. The files that are used to configure the Azure resources include: - *main.parameters.json*. - *main.bicep*. - An *app* resources directory organized by functionality. - A *core* reference library that contains the Bicep modules used by the `azd` template. - Deploys the code by using `azd deploy`. #### Expected output The `azd init` command displays output that's similar to the following lines: ```azdeveloper Initializing an app to run on Azure (azd init) ? Enter a unique environment name: [? for help] <environment-name> ? Enter a unique environment name: <environment-name> SUCCESS: Initialized environment <environment-name>. ``` The `azd up` command displays output that's similar to the following lines: ```azdeveloper ? Select an Azure Subscription to use: 3. <subscription-name> (aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e) ? Enter a value for the 'location' infrastructure parameter: 51. (US) East US 2 (eastus2) Packaging services (azd package) (✓) Done: Packaging service checkout - Container: pubsub-dapr-javascript-servicebus-aca/checkout-<environment-name>:azd-deploy-1764784418 (✓) Done: Packaging service orders - Container: pubsub-dapr-javascript-servicebus-aca/orders-<environment-name>:azd-deploy-1764784420 Provisioning Azure resources (azd provision) Provisioning Azure resources can take some time. Subscription: <subscription-name> (aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e) Location: East US 2 You can view detailed progress in the Azure Portal: https://portal.azure.com/#view/HubsExtension/DeploymentDetailsBlade/~/overview/id/%2Fsubscriptions%2Faaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e%2Fproviders%2FMicrosoft.Resources%2Fdeployments%2F<environment-name>-1764784426 (✓) Done: Resource group: rg-<environment-name> (2.805s) (✓) Done: Service Bus Namespace: sb-a1bc2de3fh4ij (17.866s) (✓) Done: Log Analytics workspace: log-a1bc2de3fh4ij (23.262s) (✓) Done: Application Insights: appi-a1bc2de3fh4ij (3.167s) (✓) Done: Portal dashboard: dash-a1bc2de3fh4ij (1.858s) (✓) Done: Container Registry: cra1bc2de3fh4ij (20.097s) (✓) Done: Container Apps Environment: cae-a1bc2de3fh4ij (1m39.71s) (✓) Done: Container App: ca-orders-a1bc2de3fh4ij (19.927s) (✓) Done: Container App: ca-checkout-a1bc2de3fh4ij (20.213s) Deploying services (azd deploy) (✓) Done: Deploying service checkout (✓) Done: Deploying service orders - Endpoint: https://ca-orders-a1bc2de3fh4ij.gentlebeach-c2de3fh4.eastus2.azurecontainerapps.io/ SUCCESS: Your up workflow to provision and deploy to Azure completed in 5 minutes 10 seconds. ``` ### Confirm successful deployment Take the following steps to verify that the `checkout` service is publishing messages to the Service Bus topic and the `order-processor` service is receiving the messages. 1. In the terminal output, copy the `checkout` container app name. 1. Sign in to the [Azure portal](https://portal.azure.com), and then search for the container app resource by name. 1. On the container app **Overview** page, select **Monitoring** > **Log stream**. :::image type="content" source="media/microservices-dapr-azd/log-streams-menu.png" alt-text="Screenshot of the Azure portal side panel. Under Monitoring, Log stream is highlighted."::: 1. On the **Log stream** page, next to **Container**, select **checkout**. :::image type="content" source="media/microservices-dapr-azd/select-checkout-container-logs.png" alt-text="Screenshot of the Log stream page for the checkout container app. In the Container list, checkout is highlighted." lightbox="media/microservices-dapr-azd/select-checkout-container-logs.png"::: 1. Confirm the `checkout` container is logging the same output as in the terminal earlier. ``` Connecting to stream... 2025-12-03T17:59:44.86984 Connecting to the container 'checkout'... 2025-12-03T17:59:44.88762 Successfully Connected to container: 'checkout' [Revision: 'ca-checkout-a1bc2de3fh4ij--azd-1010101010', Replica: 'ca-checkout-a1bc2de3fh4ij--azd-1010101010-e3fh4ij5kl-6mn7o'] 2025-12-03T17:59:20.110076973Z Published data: {"orderId":1} 2025-12-03T17:59:21.122761423Z Published data: {"orderId":2} 2025-12-03T17:59:22.134562301Z Published data: {"orderId":3} 2025-12-03T17:59:23.148699507Z Published data: {"orderId":4} 2025-12-03T17:59:24.160779162Z Published data: {"orderId":5} 2025-12-03T17:59:25.176694795Z Published data: {"orderId":6} 2025-12-03T17:59:26.189284846Z Published data: {"orderId":7} 2025-12-03T17:59:27.201353592Z Published data: {"orderId":8} 2025-12-03T17:59:28.217884685Z Published data: {"orderId":9} 2025-12-03T17:59:29.229885611Z Published data: {"orderId":10} 2025-12-03T17:59:30.242877567Z Published data: {"orderId":11} 2025-12-03T17:59:31.255062497Z Published data: {"orderId":12} 2025-12-03T17:59:32.270373602Z Published data: {"orderId":13} 2025-12-03T17:59:33.283227059Z Published data: {"orderId":14} 2025-12-03T17:59:34.297275983Z Published data: {"orderId":15} 2025-12-03T17:59:35.309770245Z Published data: {"orderId":16} 2025-12-03T17:59:36.324099049Z Published data: {"orderId":17} 2025-12-03T17:59:37.337279276Z Published data: {"orderId":18} 2025-12-03T17:59:38.351045429Z Published data: {"orderId":19} 2025-12-03T17:59:39.364701033Z Published data: {"orderId":20} ``` 1. Take similar steps for the `order-processor` service. ``` Connecting to stream... 2025-12-03T17:59:54.59128 Connecting to the container 'orders'... 2025-12-03T17:59:54.62517 Successfully Connected to container: 'orders' [Revision: 'ca-orders-h4ij5kl6mn7op--azd-1010101010', Replica: 'ca-orders-h4ij5kl6mn7op--azd-1010101010-8qr9st0uv1-wx2yz'] 2025-12-03T17:59:20.121003257Z Subscriber received: {"orderId":1} 2025-12-03T17:59:21.134397375Z Subscriber received: {"orderId":2} 2025-12-03T17:59:22.145897352Z Subscriber received: {"orderId":3} 2025-12-03T17:59:23.159802356Z Subscriber received: {"orderId":4} 2025-12-03T17:59:24.173394595Z Subscriber received: {"orderId":5} 2025-12-03T17:59:25.188890235Z Subscriber received: {"orderId":6} 2025-12-03T17:59:26.200088846Z Subscriber received: {"orderId":7} 2025-12-03T17:59:27.212526588Z Subscriber received: {"orderId":8} 2025-12-03T17:59:28.236604126Z Subscriber received: {"orderId":9} 2025-12-03T17:59:29.242356323Z Subscriber received: {"orderId":10} 2025-12-03T17:59:30.253994680Z Subscriber received: {"orderId":11} 2025-12-03T17:59:31.267712900Z Subscriber received: {"orderId":12} 2025-12-03T17:59:32.282449416Z Subscriber received: {"orderId":13} 2025-12-03T17:59:33.296803973Z Subscriber received: {"orderId":14} 2025-12-03T17:59:34.308987729Z Subscriber received: {"orderId":15} 2025-12-03T17:59:35.321011193Z Subscriber received: {"orderId":16} 2025-12-03T17:59:36.336338712Z Subscriber received: {"orderId":17} 2025-12-03T17:59:37.347838169Z Subscriber received: {"orderId":18} 2025-12-03T17:59:38.370022121Z Subscriber received: {"orderId":19} 2025-12-03T17:59:39.377157717Z Subscriber received: {"orderId":20} ``` ## Understand azd up When the `azd up` command runs successfully: - The Azure Developer CLI creates the Azure resources referenced in the [sample project ./infra directory](https://github.com/Azure-Samples/pubsub-dapr-nodejs-servicebus/tree/main/infra) in the Azure subscription you specify. You can find those Azure resources in the Azure portal. - The app is deployed to Container Apps. In the Azure portal, you can access the fully functional app. ::: zone-end ::: zone pivot="python" ## Run the Python applications locally Before you deploy the application to Container Apps, take the steps in the following sections to run the `order-processor` and `checkout` services locally with Dapr and Azure Service Bus. ### Prepare the project 1. Clone the [sample application](https://github.com/Azure-Samples/pubsub-dapr-python-servicebus) to your local machine. ```bash git clone https://github.com/Azure-Samples/pubsub-dapr-python-servicebus.git ``` 1. Go to the sample root directory. ```bash cd pubsub-dapr-python-servicebus ``` ### Run the applications by using the Dapr CLI Take the following steps to run the `order-processor` subscriber service and the `checkout` publisher service. 1. From the sample root directory, go to the *order-processor* directory. ```bash cd order-processor ``` 2. Install the dependencies. ```bash pip3 install -r requirements.txt ``` 3. Run the `order-processor` service. # [Windows](#tab/windows) ```bash dapr run --app-id order-processor --resources-path ../components/ --app-port 5001 -- python app.py ``` # [Linux](#tab/linux) ```bash dapr run --app-id order-processor --resources-path ../components/ --app-port 5001 -- python3 app.py ``` --- 4. In a new terminal window, go to the sample root directory, and then go to the *checkout* directory. ```bash cd checkout ``` 5. Install the dependencies. ```bash pip3 install -r requirements.txt ``` 6. Run the `checkout` service. # [Windows](#tab/windows) ```bash dapr run --app-id checkout --resources-path ../components/ -- python app.py ``` # [Linux](#tab/linux) ```bash dapr run --app-id checkout --resources-path ../components/ -- python3 app.py ``` --- #### Expected output In the `checkout` terminal, the `checkout` service publishes 19 messages and then temporarily pauses. ``` == APP == INFO:root:Published data: {"orderId": 1} == APP == INFO:root:Published data: {"orderId": 2} == APP == INFO:root:Published data: {"orderId": 3} == APP == INFO:root:Published data: {"orderId": 4} == APP == INFO:root:Published data: {"orderId": 5} == APP == INFO:root:Published data: {"orderId": 6} == APP == INFO:root:Published data: {"orderId": 7} == APP == INFO:root:Published data: {"orderId": 8} == APP == INFO:root:Published data: {"orderId": 9} == APP == INFO:root:Published data: {"orderId": 10} == APP == INFO:root:Published data: {"orderId": 11} == APP == INFO:root:Published data: {"orderId": 12} == APP == INFO:root:Published data: {"orderId": 13} == APP == INFO:root:Published data: {"orderId": 14} == APP == INFO:root:Published data: {"orderId": 15} == APP == INFO:root:Published data: {"orderId": 16} == APP == INFO:root:Published data: {"orderId": 17} == APP == INFO:root:Published data: {"orderId": 18} == APP == INFO:root:Published data: {"orderId": 19} ``` In the `order-processor` terminal, the `order-processor` service receives 19 messages. ``` == APP == Subscriber received : 1 == APP == 127.0.0.1 - - [03/Dec/2025 15:37:28] "POST /orders HTTP/1.1" 200 - == APP == Subscriber received : 2 == APP == 127.0.0.1 - - [03/Dec/2025 15:37:29] "POST /orders HTTP/1.1" 200 - == APP == Subscriber received : 3 == APP == 127.0.0.1 - - [03/Dec/2025 15:37:30] "POST /orders HTTP/1.1" 200 - == APP == Subscriber received : 4 == APP == 127.0.0.1 - - [03/Dec/2025 15:37:31] "POST /orders HTTP/1.1" 200 - == APP == Subscriber received : 5 == APP == 127.0.0.1 - - [03/Dec/2025 15:37:32] "POST /orders HTTP/1.1" 200 - == APP == Subscriber received : 6 == APP == 127.0.0.1 - - [03/Dec/2025 15:37:33] "POST /orders HTTP/1.1" 200 - == APP == Subscriber received : 7 == APP == 127.0.0.1 - - [03/Dec/2025 15:37:34] "POST /orders HTTP/1.1" 200 - == APP == Subscriber received : 8 == APP == 127.0.0.1 - - [03/Dec/2025 15:37:35] "POST /orders HTTP/1.1" 200 - == APP == Subscriber received : 9 == APP == 127.0.0.1 - - [03/Dec/2025 15:37:36] "POST /orders HTTP/1.1" 200 - == APP == Subscriber received : 10 == APP == 127.0.0.1 - - [03/Dec/2025 15:37:37] "POST /orders HTTP/1.1" 200 - == APP == Subscriber received : 11 == APP == 127.0.0.1 - - [03/Dec/2025 15:37:38] "POST /orders HTTP/1.1" 200 - == APP == Subscriber received : 12 == APP == 127.0.0.1 - - [03/Dec/2025 15:37:39] "POST /orders HTTP/1.1" 200 - == APP == Subscriber received : 13 == APP == 127.0.0.1 - - [03/Dec/2025 15:37:40] "POST /orders HTTP/1.1" 200 - == APP == Subscriber received : 14 == APP == 127.0.0.1 - - [03/Dec/2025 15:37:41] "POST /orders HTTP/1.1" 200 - == APP == Subscriber received : 15 == APP == 127.0.0.1 - - [03/Dec/2025 15:37:42] "POST /orders HTTP/1.1" 200 - == APP == Subscriber received : 16 == APP == 127.0.0.1 - - [03/Dec/2025 15:37:43] "POST /orders HTTP/1.1" 200 - == APP == Subscriber received : 17 == APP == 127.0.0.1 - - [03/Dec/2025 15:37:44] "POST /orders HTTP/1.1" 200 - == APP == Subscriber received : 18 == APP == 127.0.0.1 - - [03/Dec/2025 15:37:45] "POST /orders HTTP/1.1" 200 - == APP == Subscriber received : 19 == APP == 127.0.0.1 - - [03/Dec/2025 15:37:46] "POST /orders HTTP/1.1" 200 - ``` ### Stop the applications To stop the applications, open a separate terminal and run the following commands: ```sh dapr stop --app-id checkout dapr stop --app-id order-processor ``` ## Deploy the application template by using the Azure Developer CLI To deploy the application to Container Apps by using [`azd`](/azure/developer/azure-developer-cli/overview) commands, take the steps in the following sections. ### Prepare the project In a new terminal window, go to the [sample](https://github.com/Azure-Samples/pubsub-dapr-python-servicebus) root directory. ```bash cd pubsub-dapr-python-servicebus ``` ### Create and deploy by using the Azure Developer CLI 1. Run `azd init` to initialize the project. ```azdeveloper azd init ``` When prompted in the terminal, enter a unique environment name. The command uses this name as a prefix for the resource group that it creates to hold all Azure resources. 1. Run `azd up` to prepare the infrastructure and deploy the application to Container Apps in a single command. ```azdeveloper azd up ``` When prompted in the terminal, enter values for the following parameters: | Parameter | Description | | --------- | ----------- | | Azure subscription | The Azure subscription for your resources | | Azure location | The Azure location for your resources | This process can take some time to finish. While the `azd up` command runs, the output displays two Azure portal links that you can use to monitor the deployment progress. The output also demonstrates how `azd up`: - Creates and configures all necessary Azure resources via the Bicep files in the *./infra* directory by using `azd provision`. After the Azure Developer CLI deploys these resources, you can use the Azure portal to access them. The files that are used to configure the Azure resources include: - *main.parameters.json*. - *main.bicep*. - An *app* resources directory organized by functionality. - A *core* reference library that contains the Bicep modules used by the `azd` template. - Deploys the code by using `azd deploy`. #### Expected output The `azd init` command displays output that's similar to the following lines: ```azdeveloper Initializing an app to run on Azure (azd init) ? Enter a unique environment name: [? for help] <environment-name> ? Enter a unique environment name: <environment-name> SUCCESS: Initialized environment <environment-name>. ``` The `azd up` command displays output that's similar to the following lines: ```azdeveloper ? Select an Azure Subscription to use: 3. <subscription-name> (aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e) ? Enter a value for the 'location' infrastructure parameter: 51. (US) East US 2 (eastus2) Packaging services (azd package) (✓) Done: Packaging service checkout - Container: pubsub-dapr-python-servicebus-aca/checkout-<environment-name>:azd-deploy-1764794878 (✓) Done: Packaging service orders - Container: pubsub-dapr-python-servicebus-aca/orders-<environment-name>:azd-deploy-1764794880 Provisioning Azure resources (azd provision) Provisioning Azure resources can take some time. Subscription: <subscription-name> (aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e) Location: East US 2 You can view detailed progress in the Azure Portal: https://portal.azure.com/#view/HubsExtension/DeploymentDetailsBlade/~/overview/id/%2Fsubscriptions%2Faaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e%2Fproviders%2FMicrosoft.Resources%2Fdeployments%2F<environment-name>-1764794886 (✓) Done: Resource group: rg-<environment-name> (2.444s) (✓) Done: Service Bus Namespace: sb-a1bc2de3fh4ij (19.857s) (✓) Done: Log Analytics workspace: log-a1bc2de3fh4ij (21.144s) (✓) Done: Application Insights: appi-a1bc2de3fh4ij (1.154s) (✓) Done: Portal dashboard: dash-a1bc2de3fh4ij (573ms) (✓) Done: Container Registry: cra1bc2de3fh4ij (19.595s) (✓) Done: Container Apps Environment: cae-a1bc2de3fh4ij (1m26.226s) (✓) Done: Container App: ca-orders-a1bc2de3fh4ij (27.124s) (✓) Done: Container App: ca-checkout-a1bc2de3fh4ij (28.109s) Deploying services (azd deploy) (✓) Done: Deploying service checkout (✓) Done: Deploying service orders - Endpoint: https://ca-orders-a1bc2de3fh4ij.icytree-c2de3fh4.eastus2.azurecontainerapps.io/ SUCCESS: Your up workflow to provision and deploy to Azure completed in 5 minutes. ``` ### Confirm successful deployment Take the following steps to verify that the `checkout` service is publishing messages to the Service Bus topic and the `order-processor` service is receiving the messages. 1. In the terminal output, copy the `checkout` container app name. 1. Sign in to the [Azure portal](https://portal.azure.com), and then search for the container app resource by name. 1. On the container app **Overview** page, select **Monitoring** > **Log stream**. :::image type="content" source="media/microservices-dapr-azd/log-streams-menu.png" alt-text="Screenshot of the side panel in the Azure portal. Under Monitoring, Log stream is highlighted."::: 1. On the **Log stream** page, next to **Container**, select **checkout**. :::image type="content" source="media/microservices-dapr-azd/select-checkout-container-logs.png" alt-text="Screenshot of the Log stream page for the checkout container app. In the Container list, checkout is highlighted and selected." lightbox="media/microservices-dapr-azd/select-checkout-container-logs.png"::: 1. Confirm the `checkout` container is logging the same output as in the terminal earlier. ``` Connecting to stream... 2025-12-03T20:56:10.89517 Connecting to the container 'checkout'... 2025-12-03T20:56:10.92655 Successfully Connected to container: 'checkout' [Revision: 'ca-checkout-a1bc2de3fh4ij--azd-1010101010', Replica: 'ca-checkout-a1bc2de3fh4ij--azd-1010101010-e3fh4ij5kl-6mn7o'] 2025-12-03T20:55:54.971898941Z INFO:root:Published data: {"orderId": 1} 2025-12-03T20:55:55.985395409Z INFO:root:Published data: {"orderId": 2} 2025-12-03T20:55:57.002043502Z INFO:root:Published data: {"orderId": 3} 2025-12-03T20:55:58.017690382Z INFO:root:Published data: {"orderId": 4} 2025-12-03T20:55:59.032269801Z INFO:root:Published data: {"orderId": 5} 2025-12-03T20:56:00.045075250Z INFO:root:Published data: {"orderId": 6} 2025-12-03T20:56:01.058436708Z INFO:root:Published data: {"orderId": 7} 2025-12-03T20:56:02.073213603Z INFO:root:Published data: {"orderId": 8} 2025-12-03T20:56:03.088542130Z INFO:root:Published data: {"orderId": 9} 2025-12-03T20:56:04.102553097Z INFO:root:Published data: {"orderId": 10} 2025-12-03T20:56:05.116147371Z INFO:root:Published data: {"orderId": 11} 2025-12-03T20:56:06.131053744Z INFO:root:Published data: {"orderId": 12} 2025-12-03T20:56:07.144493474Z INFO:root:Published data: {"orderId": 13} 2025-12-03T20:56:08.158381479Z INFO:root:Published data: {"orderId": 14} 2025-12-03T20:56:09.175048175Z INFO:root:Published data: {"orderId": 15} 2025-12-03T20:56:10.188971144Z INFO:root:Published data: {"orderId": 16} 2025-12-03T20:56:11.202891285Z INFO:root:Published data: {"orderId": 17} 2025-12-03T20:56:12.217084672Z INFO:root:Published data: {"orderId": 18} 2025-12-03T20:56:13.229771418Z INFO:root:Published data: {"orderId": 19} ``` 1. Take similar steps for the `order-processor` service. ``` Connecting to stream... 2025-12-03T20:56:18.74960 Connecting to the container 'orders'... 2025-12-03T20:56:18.76913 Successfully Connected to container: 'orders' [Revision: 'ca-orders-h4ij5kl6mn7op--azd-1010101010', Replica: 'ca-orders-h4ij5kl6mn7op--azd-1010101010-8qr9st0uv1-wx2yz'] 2025-12-03T20:56:24.260129668Z Subscriber received : 1 2025-12-03T20:56:24.260504460Z 127.0.0.1 - - [03/Dec/2025 20:56:24] "POST /orders HTTP/1.1" 200 - 2025-12-03T20:56:25.286774893Z Subscriber received : 2 2025-12-03T20:56:25.287837138Z 127.0.0.1 - - [03/Dec/2025 20:56:25] "POST /orders HTTP/1.1" 200 - 2025-12-03T20:56:26.302102842Z Subscriber received : 3 2025-12-03T20:56:26.302508442Z 127.0.0.1 - - [03/Dec/2025 20:56:26] "POST /orders HTTP/1.1" 200 - 2025-12-03T20:56:27.316271178Z Subscriber received : 4 2025-12-03T20:56:27.317288756Z 127.0.0.1 - - [03/Dec/2025 20:56:27] "POST /orders HTTP/1.1" 200 - 2025-12-03T20:56:28.329865261Z Subscriber received : 5 2025-12-03T20:56:28.330863461Z 127.0.0.1 - - [03/Dec/2025 20:56:28] "POST /orders HTTP/1.1" 200 - 2025-12-03T20:56:29.342843607Z Subscriber received : 6 2025-12-03T20:56:29.343687271Z 127.0.0.1 - - [03/Dec/2025 20:56:29] "POST /orders HTTP/1.1" 200 - 2025-12-03T20:56:30.357753094Z Subscriber received : 7 2025-12-03T20:56:30.358124513Z 127.0.0.1 - - [03/Dec/2025 20:56:30] "POST /orders HTTP/1.1" 200 - 2025-12-03T20:56:31.380741546Z Subscriber received : 8 2025-12-03T20:56:31.381553667Z 127.0.0.1 - - [03/Dec/2025 20:56:31] "POST /orders HTTP/1.1" 200 - 2025-12-03T20:56:32.391023392Z Subscriber received : 9 2025-12-03T20:56:32.391420895Z 127.0.0.1 - - [03/Dec/2025 20:56:32] "POST /orders HTTP/1.1" 200 - 2025-12-03T20:56:33.405031572Z Subscriber received : 10 2025-12-03T20:56:33.405412361Z 127.0.0.1 - - [03/Dec/2025 20:56:33] "POST /orders HTTP/1.1" 200 - 2025-12-03T20:56:34.420146848Z Subscriber received : 11 2025-12-03T20:56:34.420589649Z 127.0.0.1 - - [03/Dec/2025 20:56:34] "POST /orders HTTP/1.1" 200 - 2025-12-03T20:56:35.432973524Z Subscriber received : 12 2025-12-03T20:56:35.434080392Z 127.0.0.1 - - [03/Dec/2025 20:56:35] "POST /orders HTTP/1.1" 200 - 2025-12-03T20:56:36.451629817Z Subscriber received : 13 2025-12-03T20:56:36.452061763Z 127.0.0.1 - - [03/Dec/2025 20:56:36] "POST /orders HTTP/1.1" 200 - 2025-12-03T20:56:37.467384128Z Subscriber received : 14 2025-12-03T20:56:37.467686070Z 127.0.0.1 - - [03/Dec/2025 20:56:37] "POST /orders HTTP/1.1" 200 - 2025-12-03T20:56:38.480558316Z Subscriber received : 15 2025-12-03T20:56:38.481147786Z 127.0.0.1 - - [03/Dec/2025 20:56:38] "POST /orders HTTP/1.1" 200 - 2025-12-03T20:56:39.493898658Z Subscriber received : 16 2025-12-03T20:56:39.494203912Z 127.0.0.1 - - [03/Dec/2025 20:56:39] "POST /orders HTTP/1.1" 200 - 2025-12-03T20:56:40.508312320Z Subscriber received : 17 2025-12-03T20:56:40.508685327Z 127.0.0.1 - - [03/Dec/2025 20:56:40] "POST /orders HTTP/1.1" 200 - 2025-12-03T20:56:41.534284222Z Subscriber received : 18 2025-12-03T20:56:41.534598586Z 127.0.0.1 - - [03/Dec/2025 20:56:41] "POST /orders HTTP/1.1" 200 - 2025-12-03T20:56:42.559478561Z Subscriber received : 19 2025-12-03T20:56:42.559954290Z 127.0.0.1 - - [03/Dec/2025 20:56:42] "POST /orders HTTP/1.1" 200 - ``` ## Understand azd up When the `azd up` command runs successfully: - The Azure Developer CLI creates the Azure resources referenced in the [sample project ./infra directory](https://github.com/Azure-Samples/pubsub-dapr-python-servicebus/tree/main/infra) in the Azure subscription you specify. You can find those Azure resources in the Azure portal. - The app is deployed to Container Apps. In the Azure portal, you can access the fully functional app. ::: zone-end ::: zone pivot="csharp" ## Run the .NET applications locally Before you deploy the application to Container Apps, take the steps in the following sections to run the `order-processor` and `checkout` services locally with Dapr and Azure Service Bus. ### Prepare the project 1. Clone the [sample application](https://github.com/Azure-Samples/pubsub-dapr-csharp-servicebus) to your local machine. ```bash git clone https://github.com/Azure-Samples/pubsub-dapr-csharp-servicebus.git ``` 1. Go to the sample root directory. ```bash cd pubsub-dapr-csharp-servicebus ``` ### Run the applications by using the Dapr CLI Take the following steps to run the `order-processor` subscriber service and the `checkout` publisher service. 1. From the sample root directory, go to the *order-processor* directory. ```bash cd order-processor ``` 1. Install the dependencies. ```bash dotnet build ``` 1. Run the `order-processor` service. ```bash dapr run --app-id order-processor --resources-path ../components/ --app-port 7001 -- dotnet run --project . ``` 1. In a new terminal window, go to the sample root directory, and then go to the *checkout* directory. ```bash cd checkout ``` 1. Install the dependencies. ```bash dotnet build ``` 1. Run the `checkout` service. ```bash dapr run --app-id checkout --resources-path ../components/ -- dotnet run --project . ``` #### Expected output In the `checkout` terminal, the `checkout` service publishes 20 messages and then temporarily pauses. ``` == APP == Published data: Order { OrderId = 1 } == APP == Published data: Order { OrderId = 2 } == APP == Published data: Order { OrderId = 3 } == APP == Published data: Order { OrderId = 4 } == APP == Published data: Order { OrderId = 5 } == APP == Published data: Order { OrderId = 6 } == APP == Published data: Order { OrderId = 7 } == APP == Published data: Order { OrderId = 8 } == APP == Published data: Order { OrderId = 9 } == APP == Published data: Order { OrderId = 10 } == APP == Published data: Order { OrderId = 11 } == APP == Published data: Order { OrderId = 12 } == APP == Published data: Order { OrderId = 13 } == APP == Published data: Order { OrderId = 14 } == APP == Published data: Order { OrderId = 15 } == APP == Published data: Order { OrderId = 16 } == APP == Published data: Order { OrderId = 17 } == APP == Published data: Order { OrderId = 18 } == APP == Published data: Order { OrderId = 19 } == APP == Published data: Order { OrderId = 20 } ``` In the `order-processor` terminal, the `order-processor` service receives 20 messages. ``` == APP == Subscriber received : Order { OrderId = 1 } == APP == Subscriber received : Order { OrderId = 2 } == APP == Subscriber received : Order { OrderId = 3 } == APP == Subscriber received : Order { OrderId = 4 } == APP == Subscriber received : Order { OrderId = 5 } == APP == Subscriber received : Order { OrderId = 6 } == APP == Subscriber received : Order { OrderId = 7 } == APP == Subscriber received : Order { OrderId = 8 } == APP == Subscriber received : Order { OrderId = 9 } == APP == Subscriber received : Order { OrderId = 10 } == APP == Subscriber received : Order { OrderId = 11 } == APP == Subscriber received : Order { OrderId = 12 } == APP == Subscriber received : Order { OrderId = 13 } == APP == Subscriber received : Order { OrderId = 14 } == APP == Subscriber received : Order { OrderId = 15 } == APP == Subscriber received : Order { OrderId = 16 } == APP == Subscriber received : Order { OrderId = 17 } == APP == Subscriber received : Order { OrderId = 18 } == APP == Subscriber received : Order { OrderId = 19 } == APP == Subscriber received : Order { OrderId = 20 } ``` ### Stop the applications To stop the applications, open a separate terminal and run the following commands: ```sh dapr stop --app-id checkout dapr stop --app-id order-processor ``` ## Deploy the application template by using the Azure Developer CLI To deploy the application to Container Apps by using [`azd`](/azure/developer/azure-developer-cli/overview) commands, take the steps in the following sections. ### Prepare the project In a new terminal window, go to the [sample](https://github.com/Azure-Samples/pubsub-dapr-csharp-servicebus) root directory. ```bash cd pubsub-dapr-csharp-servicebus ``` ### Create and deploy by using the Azure Developer CLI 1. Run `azd init` to initialize the project. ```azdeveloper azd init ``` When prompted in the terminal, enter a unique environment name. The command uses this name as a prefix for the resource group that it creates to hold all Azure resources. 1. Run `azd up` to prepare the infrastructure and deploy the application to Container Apps in a single command. ```azdeveloper azd up ``` When prompted in the terminal, enter values for the following parameters: | Parameter | Description | | --------- | ----------- | | Azure subscription | The Azure subscription for your resources | | Azure location | The Azure location for your resources | This process can take some time to finish. While the `azd up` command runs, the output displays two Azure portal links that you can use to monitor the deployment progress. The output also demonstrates how `azd up`: - Creates and configures all necessary Azure resources via the Bicep files in the *./infra* directory by using `azd provision`. After the Azure Developer CLI deploys these resources, you can use the Azure portal to access them. The files that are used to configure the Azure resources include: - *main.parameters.json*. - *main.bicep*. - An *app* resources directory organized by functionality. - A *core* reference library that contains the Bicep modules used by the `azd` template. - Deploys the code by using `azd deploy`. #### Expected output The `azd init` command displays output that's similar to the following lines: ```azdeveloper Initializing an app to run on Azure (azd init) ? Enter a unique environment name: [? for help] <environment-name> ? Enter a unique environment name: <environment-name> SUCCESS: Initialized environment <environment-name>. ``` The `azd up` command displays output that's similar to the following lines: ```azdeveloper ? Select an Azure Subscription to use: 3. <subscription-name> (aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e) ? Enter a value for the 'location' infrastructure parameter: 51. (US) East US 2 (eastus2) Packaging services (azd package) (✓) Done: Packaging service checkout - Container: pubsub-dapr-csharp-servicebus/checkout-<environment-name>:azd-deploy-1764796559 (✓) Done: Packaging service orders - Container: pubsub-dapr-csharp-servicebus/orders-<environment-name>:azd-deploy-1764796569 Provisioning Azure resources (azd provision) Provisioning Azure resources can take some time. Subscription: <subscription-name> (aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e) Location: East US 2 You can view detailed progress in the Azure Portal: https://portal.azure.com/#view/HubsExtension/DeploymentDetailsBlade/~/overview/id/%2Fsubscriptions%2Faaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e%2Fproviders%2FMicrosoft.Resources%2Fdeployments%2F<environment-name>-1764796579 (✓) Done: Resource group: rg-<environment-name> (1.727s) (✓) Done: Service Bus Namespace: sb-a1bc2de3fh4ij (18.228s) (✓) Done: Log Analytics workspace: log-a1bc2de3fh4ij (23.214s) (✓) Done: Application Insights: appi-a1bc2de3fh4ij (1.006s) (✓) Done: Portal dashboard: dash-a1bc2de3fh4ij (2.077s) (✓) Done: Container Registry: cra1bc2de3fh4ij (18.492s) (✓) Done: Container Apps Environment: cae-a1bc2de3fh4ij (1m53.753s) (✓) Done: Container App: ca-orders-a1bc2de3fh4ij (40.053s) (✓) Done: Container App: ca-checkout-a1bc2de3fh4ij (29.412s) Deploying services (azd deploy) (✓) Done: Deploying service checkout (✓) Done: Deploying service orders - Endpoint: https://ca-orders-a1bc2de3fh4ij.whitecoast-c2de3fh4.eastus2.azurecontainerapps.io/ SUCCESS: Your up workflow to provision and deploy to Azure completed in 6 minutes 15 seconds. ``` ### Confirm successful deployment Take the following steps to verify that the `checkout` service is publishing messages to the Service Bus topic and the `order-processor` service is receiving the messages. 1. Copy the `checkout` container app name from the terminal output. 1. Sign in to the [Azure portal](https://portal.azure.com) and search for the container app resource by name. 1. In the Container Apps dashboard, select **Monitoring** > **Log stream**. :::image type="content" source="media/microservices-dapr-azd/log-streams-menu.png" alt-text="Screenshot of the Azure portal. On the side panel, under Monitoring, Log stream is highlighted."::: 1. On the **Log stream** page, next to **Container**, select **checkout**. :::image type="content" source="media/microservices-dapr-azd/select-checkout-container-logs.png" alt-text="Screenshot of the Log stream page for the checkout container app. Above the log stream, in the Container list, checkout is highlighted." lightbox="media/microservices-dapr-azd/select-checkout-container-logs.png"::: 1. Confirm the `checkout` container is logging the same output as in the terminal earlier. ``` Connecting to stream... 2025-12-03T21:22:38.59199 Connecting to the container 'checkout'... 2025-12-03T21:22:38.61294 Successfully Connected to container: 'checkout' [Revision: 'ca-checkout-a1bc2de3fh4ij--azd-1010101010', Replica: 'ca-checkout-a1bc2de3fh4ij--azd-1010101010-e3fh4ij5kl-6mn7o'] 2025-12-03T21:22:25.764173919Z Published data: Order { OrderId = 1 } 2025-12-03T21:22:26.775186594Z Published data: Order { OrderId = 2 } 2025-12-03T21:22:27.785402134Z Published data: Order { OrderId = 3 } 2025-12-03T21:22:28.795885226Z Published data: Order { OrderId = 4 } 2025-12-03T21:22:29.818661172Z Published data: Order { OrderId = 5 } 2025-12-03T21:22:30.833916028Z Published data: Order { OrderId = 6 } 2025-12-03T21:22:31.847722919Z Published data: Order { OrderId = 7 } 2025-12-03T21:22:32.858583147Z Published data: Order { OrderId = 8 } 2025-12-03T21:22:33.868997259Z Published data: Order { OrderId = 9 } 2025-12-03T21:22:34.879750628Z Published data: Order { OrderId = 10 } 2025-12-03T21:22:35.889718195Z Published data: Order { OrderId = 11 } 2025-12-03T21:22:36.905244880Z Published data: Order { OrderId = 12 } 2025-12-03T21:22:37.915565325Z Published data: Order { OrderId = 13 } 2025-12-03T21:22:38.926142458Z Published data: Order { OrderId = 14 } 2025-12-03T21:22:39.937747578Z Published data: Order { OrderId = 15 } 2025-12-03T21:22:40.952842205Z Published data: Order { OrderId = 16 } 2025-12-03T21:22:41.964924464Z Published data: Order { OrderId = 17 } 2025-12-03T21:22:42.974247022Z Published data: Order { OrderId = 18 } 2025-12-03T21:22:43.988211319Z Published data: Order { OrderId = 19 } 2025-12-03T21:22:44.997345767Z Published data: Order { OrderId = 20 } ``` 1. Do the same for the `order-processor` service. ``` Connecting to stream... 2025-12-03T21:23:11.36616 Connecting to the container 'orders'... 2025-12-03T21:23:11.38606 Successfully Connected to container: 'orders' [Revision: 'ca-orders-h4ij5kl6mn7op--azd-1010101010', Replica: 'ca-orders-h4ij5kl6mn7op--azd-1010101010-8qr9st0uv1-wx2yz'] 2025-12-03T21:22:56.016634660Z Subscriber received : Order { OrderId = 1 } 2025-12-03T21:22:57.092104858Z Subscriber received : Order { OrderId = 2 } 2025-12-03T21:22:58.037571888Z Subscriber received : Order { OrderId = 3 } 2025-12-03T21:22:59.047149782Z Subscriber received : Order { OrderId = 4 } 2025-12-03T21:23:00.057088303Z Subscriber received : Order { OrderId = 5 } 2025-12-03T21:23:01.085777239Z Subscriber received : Order { OrderId = 6 } 2025-12-03T21:23:02.083886674Z Subscriber received : Order { OrderId = 7 } 2025-12-03T21:23:03.091921022Z Subscriber received : Order { OrderId = 8 } 2025-12-03T21:23:04.120860392Z Subscriber received : Order { OrderId = 9 } 2025-12-03T21:23:05.127930191Z Subscriber received : Order { OrderId = 10 } 2025-12-03T21:23:06.137896372Z Subscriber received : Order { OrderId = 11 } 2025-12-03T21:23:07.242953880Z Subscriber received : Order { OrderId = 12 } 2025-12-03T21:23:08.255497831Z Subscriber received : Order { OrderId = 13 } 2025-12-03T21:23:09.264101960Z Subscriber received : Order { OrderId = 14 } 2025-12-03T21:23:10.278569058Z Subscriber received : Order { OrderId = 15 } 2025-12-03T21:23:11.297722094Z Subscriber received : Order { OrderId = 16 } 2025-12-03T21:23:12.294944386Z Subscriber received : Order { OrderId = 17 } 2025-12-03T21:23:13.306328648Z Subscriber received : Order { OrderId = 18 } 2025-12-03T21:23:14.322317879Z Subscriber received : Order { OrderId = 19 } 2025-12-03T21:23:15.076995284Z Subscriber received : Order { OrderId = 20 } ``` ## Understand azd up When the `azd up` command runs successfully: - The Azure Developer CLI creates the Azure resources referenced in the [sample project ./infra directory](https://github.com/Azure-Samples/pubsub-dapr-csharp-servicebus/tree/main/infra) in the Azure subscription you specify. You can find those Azure resources in the Azure portal. - The app is deployed to Container Apps. In the Azure portal, you can access the fully functional app. ::: zone-end ## Clean up resources If you're not going to continue to use this application, use the following command to delete the Azure resources you created: ```azdeveloper azd down ``` ## Related content - For more information about deploying applications to Container Apps, see [Quickstart: Deploy a Dapr application to Azure Container Apps using the Azure CLI](./microservices-dapr.md). - For information about using a token to check that requests to your app come from Dapr, see [Enable token authentication for Dapr requests](./dapr-authentication-token.md). - For information about making your applications compatible with `azd`, see [Create Azure Developer CLI templates overview](/azure/developer/azure-developer-cli/make-azd-compatible).
Success! Branch created successfully. Create Pull Request on GitHub
Error: