|
1 | 1 | --- |
2 | 2 | title: Communicate between container apps in Azure Container Apps |
3 | | -description: Learn how to communicate between different container apps in the same environment in Azure Container Apps. |
4 | | -services: container-apps |
| 3 | +description: Learn how container apps communicate within the same environment using FQDNs, app names, Dapr service invocation, and custom domains in Azure Container Apps. |
5 | 4 | author: craigshoemaker |
6 | | -ms.service: azure-container-apps |
7 | | -ms.topic: concept-article |
8 | | -ms.date: 04/07/2025 |
9 | 5 | ms.author: cshoe |
| 6 | +ms.service: azure-container-apps |
| 7 | +ms.topic: conceptual |
| 8 | +ms.date: 03/31/2026 |
| 9 | +ai-usage: ai-assisted |
10 | 10 | --- |
11 | 11 |
|
12 | 12 | # Communicate between container apps in Azure Container Apps |
13 | 13 |
|
14 | | -Azure Container Apps exposes each container app through a domain name if [ingress](ingress-overview.md) is enabled. You can expose ingress endpoints either publicly to the world or to the other container apps in the same environment. Alternatively, you can limit ingress to only other container apps in the same [environment](environment.md). |
| 14 | +<!-- Source: Q1, Q2, Q3 --> |
| 15 | + |
| 16 | +Azure Container Apps provides built-in service discovery and routing so your container apps can communicate with each other without managing infrastructure. When you deploy multiple container apps to the same [environment](environment.md), the platform handles DNS resolution, load balancing, and secure traffic routing automatically. |
15 | 17 |
|
16 | | -Application code can call other container apps in the same environment using one of the following methods: |
| 18 | +If [ingress](ingress-overview.md) is enabled, each container app gets a domain name. You can make that endpoint available publicly or restrict it to other container apps in the same environment. <!-- Source: Q1 --> |
17 | 19 |
|
18 | | -- Default fully qualified domain name (FQDN) |
19 | | -- A custom domain name |
20 | | -- The container app name, for instance `http://<APP_NAME>` for internal requests |
21 | | -- A Dapr URL |
| 20 | +Container apps can reach each other through any of these methods: |
| 21 | + |
| 22 | +- **Fully qualified domain name (FQDN)** : the default generated domain |
| 23 | +- **App name**: a short-form `http://<APP_NAME>` address for internal calls |
| 24 | +- **Dapr service invocation**: a sidecar-based approach with built-in retries and observability |
| 25 | +- **Custom domain**: your own domain name with a managed certificate |
22 | 26 |
|
23 | 27 | > [!NOTE] |
24 | | -> When you call another container in the same environment using the FQDN or app name, the network traffic never leaves the environment. |
| 28 | +> When you call another container app in the same environment by using the FQDN or app name, network traffic never leaves the environment. |
| 29 | +
|
| 30 | +## Why it matters |
| 31 | + |
| 32 | +<!-- Source: Q3, Q5 --> |
25 | 33 |
|
26 | | -A sample solution showing how you can call between containers using both the FQDN Location or Dapr can be found on [Azure Samples](https://github.com/Azure-Samples/container-apps-connect-multiple-apps) |
| 34 | +In a microservices architecture, services need to call each other reliably. Azure Container Apps removes the operational burden of setting up service discovery, managing DNS records, and configuring reverse proxies. |
27 | 35 |
|
28 | | -## Location |
| 36 | +Here's what the platform handles for you: |
29 | 37 |
|
30 | | -A container app's location is composed of values associated with its environment, name, and region. Available through the `azurecontainerapps.io` top-level domain, the fully qualified domain name (FQDN) uses: |
| 38 | +- **Automatic DNS registration**: Every container app gets a resolvable hostname as soon as it's deployed. |
| 39 | +- **Proxy-managed routing**: All inter-app traffic flows through a built-in Envoy proxy layer that handles TLS termination, traffic splitting, and load balancing. <!-- Source: Q3, Q5 --> |
| 40 | +- **Environment-scoped isolation**: Internal endpoints are only reachable from within the same environment, creating a natural security boundary. <!-- Source: Q1 --> |
| 41 | +- **Protocol flexibility**: Communication over HTTP/1.1, HTTP/2 (for gRPC), or raw TCP depending on your workload needs. <!-- Source: Q6 --> |
31 | 42 |
|
32 | | -- The container app name |
33 | | -- The environment unique identifier |
34 | | -- Region name |
| 43 | +These capabilities mean you can focus on your application logic rather than networking plumbing. |
35 | 44 |
|
36 | | -The following diagram shows how these values are used to compose a container app's fully qualified domain name. |
| 45 | +## Container app location (FQDN) |
| 46 | + |
| 47 | +<!-- Source: Q2, Q4 --> |
| 48 | + |
| 49 | +Each container app's fully qualified domain name is composed of the app name, a unique environment identifier, and the region. These domain fragments all fall under the `azurecontainerapps.io` top-level domain. |
37 | 50 |
|
38 | 51 | :::image type="content" source="media/connect-apps/azure-container-apps-location.png" alt-text="Azure Container Apps container app fully qualified domain name."::: |
39 | 52 |
|
| 53 | +### External and internal FQDNs |
| 54 | + |
| 55 | +<!-- Source: Q1, Q2 --> |
| 56 | + |
| 57 | +The ingress visibility setting controls whether your app is reachable from outside the environment: |
| 58 | + |
| 59 | +| Visibility | FQDN pattern | Reachable from | |
| 60 | +|---|---|---| |
| 61 | +| **External** | `<APP_NAME>.<ENVIRONMENT_UNIQUE_ID>.<REGION>.azurecontainerapps.io` | Anywhere (public internet) | |
| 62 | +| **Internal** | `<APP_NAME>.internal.<ENVIRONMENT_UNIQUE_ID>.<REGION>.azurecontainerapps.io` | Same environment only | |
| 63 | + |
| 64 | +When you set ingress to **internal**, the FQDN includes an `.internal.` segment. Other container apps in the same environment can still reach the app using this address, but requests from outside the environment receive a `404` response from the environment's proxy. The DNS name resolves to the environment's shared IP, but the proxy rejects the request because the app is internal-only. <!-- Source: Q1 --> |
| 65 | + |
40 | 66 | [!INCLUDE [container-apps-get-fully-qualified-domain-name](../../includes/container-apps-get-fully-qualified-domain-name.md)] |
41 | 67 |
|
42 | | -### Dapr location |
| 68 | +### Revision label FQDNs |
| 69 | + |
| 70 | +<!-- Source: Q11 --> |
| 71 | + |
| 72 | +When you assign labels to specific revisions, each label gets its own unique FQDN using a triple-dash separator: |
| 73 | + |
| 74 | +``` |
| 75 | +<APP_NAME>---<LABEL>.<ENVIRONMENT_UNIQUE_ID>.<REGION>.azurecontainerapps.io |
| 76 | +``` |
43 | 77 |
|
44 | | -Developing microservices often requires you to implement patterns common to distributed architecture. Dapr allows you to secure microservices with mutual Transport Layer Security (TLS) (client certificates), trigger retries when errors occur, and take advantage of distributed tracing when Azure Application Insights is enabled. |
| 78 | +For internal apps, the pattern includes the `.internal.` segment: |
45 | 79 |
|
46 | | -A microservice that uses Dapr is available through the following URL pattern: |
| 80 | +``` |
| 81 | +<APP_NAME>---<LABEL>.internal.<ENVIRONMENT_UNIQUE_ID>.<REGION>.azurecontainerapps.io |
| 82 | +``` |
47 | 83 |
|
48 | | -:::image type="content" source="media/connect-apps/azure-container-apps-location-dapr.png" alt-text="Azure Container Apps container app location with Dapr."::: |
| 84 | +Label FQDNs let you send traffic to a specific revision directly. This practice is useful for testing new versions, running A/B experiments, or providing stable endpoints for specific revision deployments. <!-- Source: Q11 --> |
49 | 85 |
|
50 | 86 | ## Call a container app by name |
51 | 87 |
|
52 | | -You can call a container app by doing by sending a request to `http://<CONTAINER_APP_NAME>` from another app in the environment. |
| 88 | +<!-- Source: Q3, Q14 --> |
| 89 | + |
| 90 | +The most straightforward way to call another container app from within the same environment is by its name. Send a request to `http://<CONTAINER_APP_NAME>`, and the environment's built-in DNS resolves the name automatically. |
| 91 | + |
| 92 | +``` |
| 93 | +http://my-backend-api |
| 94 | +``` |
| 95 | + |
| 96 | +### How DNS resolution works |
| 97 | + |
| 98 | +<!-- Source: Q3 --> |
| 99 | + |
| 100 | +Behind the scenes, Azure Container Apps uses a custom DNS configuration that translates container app names into routable addresses. When your app makes a request to another app's name or FQDN: |
| 101 | + |
| 102 | +1. The environment's DNS server resolves the hostname to the Envoy proxy service address. |
| 103 | +1. The Envoy proxy identifies the target app from the original hostname. |
| 104 | +1. The proxy routes the request to the correct revision(s) based on your traffic configuration. |
| 105 | + |
| 106 | +This architecture means container apps never communicate directly with each other's pods. All traffic passes through the proxy layer, which provides TLS termination, load balancing, and traffic splitting. <!-- Source: Q3, Q5, Q14 --> |
| 107 | + |
| 108 | +> [!TIP] |
| 109 | +> Use the short app name (`http://<APP_NAME>`) for calls between container apps in the same environment. It's simpler than the full FQDN and works the same way since the DNS resolves both patterns through the same proxy. |
| 110 | +
|
| 111 | +## Transport protocols |
| 112 | + |
| 113 | +<!-- Source: Q6 --> |
| 114 | + |
| 115 | +Container apps support three transport modes for ingress, configured through the `transport` property: |
| 116 | + |
| 117 | +| Transport | Use case | Details | |
| 118 | +|---|---|---| |
| 119 | +| **Auto** (default) | Standard web APIs and services | Negotiates HTTP/1.1 and HTTP/2 automatically | |
| 120 | +| **HTTP/2** | gRPC services | Enables HTTP/2 end-to-end, required for gRPC | |
| 121 | +| **TCP** | Non-HTTP protocols (databases, custom protocols) | Raw TCP connections with port mapping | |
| 122 | + |
| 123 | +> [!NOTE] |
| 124 | +> External TCP ingress requires a [custom VNet](networking.md). If you try to create an external TCP app without a custom VNet, you receive a `ContainerAppTcpRequiresVnet` error. Internal TCP ingress works without a custom VNet. |
| 125 | +
|
| 126 | +When you use TCP transport, you can also expose extra ports beyond the primary ingress port. Each extra port creates a separate TCP endpoint that other apps in the environment can connect to. <!-- Source: Q13 --> |
| 127 | + |
| 128 | +## Traffic splitting and revision routing |
| 129 | + |
| 130 | +<!-- Source: Q12 --> |
| 131 | + |
| 132 | +Azure Container Apps supports three revision modes that affect how traffic is distributed between container apps: |
| 133 | + |
| 134 | +| Mode | Behavior | |
| 135 | +|---|---| |
| 136 | +| **Single** | All traffic goes to the latest active revision. | |
| 137 | +| **Multiple** | Traffic splits across revisions by percentage, based on your traffic rules. | |
| 138 | +| **Labels** | Each labeled revision gets a unique FQDN for direct access. | |
| 139 | + |
| 140 | +In **multiple** mode, when another container app calls your app's FQDN, the proxy automatically distributes requests across revisions according to your configured weights. In **labels** mode, callers can target a specific revision using its [label FQDN](#revision-label-fqdns). |
| 141 | + |
| 142 | +For more information, see [Revisions in Azure Container Apps](revisions.md). |
| 143 | + |
| 144 | +## Dapr service invocation |
| 145 | + |
| 146 | +<!-- Source: Q7, Q8, Q9 --> |
| 147 | + |
| 148 | +[Dapr](https://docs.dapr.io) (Distributed Application Runtime) provides a sidecar-based approach to inter-app communication. By enabling Dapr, your container apps gain built-in service invocation with mutual TLS, automatic retries, and distributed tracing through Azure Application Insights. |
| 149 | + |
| 150 | +:::image type="content" source="media/connect-apps/azure-container-apps-location-dapr.png" alt-text="Diagram showing Azure Container Apps container app location with Dapr."::: |
53 | 151 |
|
54 | | -## Next steps |
| 152 | +### How Dapr invocation works |
| 153 | + |
| 154 | +<!-- Source: Q7 --> |
| 155 | + |
| 156 | +Each Dapr-enabled container app runs a sidecar process alongside your application. To call another Dapr-enabled app, make a local HTTP request to the Dapr sidecar, which handles service discovery and routing: |
| 157 | + |
| 158 | +``` |
| 159 | +http://localhost:3500/v1.0/invoke/<DAPR_APP_ID>/method/<METHOD_NAME> |
| 160 | +``` |
| 161 | + |
| 162 | +For example, to call the `catalog` method on an app with a Dapr App ID of `order-processor`: |
| 163 | + |
| 164 | +``` |
| 165 | +http://localhost:3500/v1.0/invoke/order-processor/method/catalog |
| 166 | +``` |
| 167 | + |
| 168 | +The sidecar resolves the target app through a dedicated DNS domain and routes the request through the Envoy proxy layer. This is the same infrastructure that handles FQDN-based routing. <!-- Source: Q9 --> |
| 169 | + |
| 170 | +> [!NOTE] |
| 171 | +> Dapr uses its own DNS resolution path (the `.dapr` domain) separate from the standard FQDN resolution. Both paths route through the environment's proxy infrastructure. <!-- Source: Q9 --> |
| 172 | +
|
| 173 | +### Dapr App ID |
| 174 | + |
| 175 | +<!-- Source: Q7, Q8 --> |
| 176 | + |
| 177 | +The Dapr App ID is the identity other apps use to invoke your service. If you don't set an explicit App ID, the Dapr runtime defaults to your container app name. The ARM API shows `appId: null` when you don't configure a custom ID, but the runtime applies the app name automatically. Set a custom App ID in your Dapr configuration if you need a different identifier. |
| 178 | + |
| 179 | +Dapr App IDs must be unique within an environment. If you try to deploy a container app with a Dapr App ID that's already in use by another app, the container app resource is created but its revision fails to provision (`provisioningState: Failed`). The error message identifies the conflicting App ID and the app that owns it. <!-- Source: Q8 --> |
| 180 | + |
| 181 | +### Dapr-only apps (no HTTP ingress) |
| 182 | + |
| 183 | +<!-- Source: Q21 --> |
| 184 | + |
| 185 | +You can enable Dapr on a container app without configuring HTTP ingress. In this case, the app isn't reachable through an FQDN or app name, but other Dapr-enabled apps can still invoke it through Dapr service invocation. This pattern is useful for background workers or event processors that only need to receive calls from other services in the mesh. <!-- Source: Q21 --> |
| 186 | + |
| 187 | +> [!TIP] |
| 188 | +> When you create a no-ingress app with the Azure CLI, omit both the `--ingress` and `--target-port` flags. Including `--target-port` without `--ingress` returns a usage error. |
| 189 | +
|
| 190 | +### Dapr sidecar configuration |
| 191 | + |
| 192 | +<!-- Source: Q16 --> |
| 193 | + |
| 194 | +You configure the Dapr sidecar through your container app's properties. Key settings include: |
| 195 | + |
| 196 | +| Setting | Description | |
| 197 | +|---|---| |
| 198 | +| `appId` | The Dapr App ID (defaults to the container app name) | |
| 199 | +| `appPort` | The port your app listens on (falls back to the ingress target port) | |
| 200 | +| `appProtocol` | Protocol for Dapr-to-app communication (for example, `http`, `grpc`) | |
| 201 | +| `logLevel` | Dapr sidecar log verbosity | |
| 202 | +| `enableApiLogging` | Whether to log Dapr API calls | |
| 203 | +| `httpMaxRequestSize` | Maximum request body size in MB for Dapr's HTTP server | |
| 204 | +| `httpReadBufferSize` | Maximum size of the HTTP read buffer in KB | |
| 205 | + |
| 206 | +For more information on configuring Dapr with Azure Container Apps, see [Dapr integration with Azure Container Apps](dapr-overview.md). |
| 207 | + |
| 208 | +## Security for inter-app communication |
| 209 | + |
| 210 | +<!-- Source: Q19 --> |
| 211 | + |
| 212 | +Azure Container Apps includes several security features that affect how container apps communicate: |
| 213 | + |
| 214 | +- **TLS by default**: All traffic between container apps routes through the Envoy proxy, which handles TLS termination. Set `allowInsecure` to `false` (the default) to enforce HTTPS redirects. <!-- Source: Q19 --> |
| 215 | +- **Client certificate mode (mTLS)**: Configure mutual TLS by setting the client certificate mode to `require`, `accept`, or `ignore`. <!-- Source: Q19 --> |
| 216 | +- **IP restrictions**: Define allow or deny rules to restrict which IP addresses can reach your app. <!-- Source: Q19 --> |
| 217 | +- **CORS policies**: Configure cross-origin resource sharing rules for browser-based clients calling your container apps. <!-- Source: Q19 --> |
| 218 | + |
| 219 | +> [!NOTE] |
| 220 | +> When you use Dapr service invocation, the Dapr sidecars automatically secure communication with mutual TLS between services. You don't need to configure mTLS separately for Dapr-to-Dapr calls. |
| 221 | +
|
| 222 | +For more information, see [Ingress in Azure Container Apps](ingress-overview.md). |
| 223 | + |
| 224 | +## Custom domains |
| 225 | + |
| 226 | +<!-- Source: Q18 --> |
| 227 | + |
| 228 | +You can map your own domain names to a container app by configuring custom domains on the ingress settings. Each custom domain can reference a managed or uploaded TLS certificate. <!-- Source: Q18 --> |
| 229 | + |
| 230 | +Custom domains are registered alongside the default FQDN, so your app responds to both addresses. When other container apps in the environment need to reach your app, they can use either the default FQDN, the app name, or your custom domain. |
| 231 | + |
| 232 | +For more information, see [Custom domains in Azure Container Apps](custom-domains-managed-certificates.md). |
| 233 | + |
| 234 | +## Sample solution |
| 235 | + |
| 236 | +A sample showing how to call between containers using both the FQDN and Dapr is available on [Azure Samples](https://github.com/Azure-Samples/container-apps-connect-multiple-apps). |
| 237 | + |
| 238 | +## Related concepts |
| 239 | + |
| 240 | +Understanding inter-app communication in Azure Container Apps connects to several related topics: |
| 241 | + |
| 242 | +- [Environments in Azure Container Apps](environment.md): The shared boundary where container apps discover and communicate with each other |
| 243 | +- [Ingress in Azure Container Apps](ingress-overview.md): How to configure external and internal endpoints, TLS, and routing rules |
| 244 | +- [Dapr integration with Azure Container Apps](dapr-overview.md): Deeper coverage of Dapr components, pub/sub, and state management alongside service invocation |
| 245 | +- [Networking in Azure Container Apps](networking.md): VNet integration, private endpoints, and network security for your environment |
| 246 | +- [Revisions in Azure Container Apps](revisions.md) : How revision modes and traffic splitting affect inter-app routing |
| 247 | + |
| 248 | +## Next step |
55 | 249 |
|
56 | 250 | > [!div class="nextstepaction"] |
57 | | -> [Get started](get-started.md) |
| 251 | +> [Configure ingress for your container app](ingress-how-to.md) |
| 252 | +
|
0 commit comments