Service-to-Service Communication¶
Connect multiple Container Apps within the same environment.
Overview¶
Container Apps in the same environment can communicate: - Via internal DNS names - Without exposing to public internet - With optional Dapr service invocation
For the broader ingress decision model, including how internal-only app ingress differs from environment-level private exposure, see Ingress in Azure Container Apps.
Do not hardcode revision-specific endpoints
Use app-level internal hostnames, not revision hostnames, for service calls. Revision names change during deployments and break static routing assumptions.
Internal DNS¶
Each Container App gets an internal FQDN:
Or simply use the app name within the same environment:
Internal Resolution Flow¶
flowchart TD
subgraph Env [Managed Environment]
subgraph Calling [Calling App]
APP1[Frontend]
end
subgraph Target [Target App]
APP2[Backend]
end
DNS[Internal DNS Resolver]
INV[Envoy Ingress]
end
APP1 -- 1. Resolve 'ca-backend' --> DNS
DNS -- 2. Returns Private IP --> APP1
APP1 -- 3. Request (Port 80/443) --> INV
INV -- 4. Route to Revision --> APP2 Example: Frontend + Backend¶
Backend API (internal only):¶
resource backendApp 'Microsoft.App/containerApps@2023-05-01' = {
name: 'ca-backend'
properties: {
configuration: {
ingress: {
external: false // Internal only
targetPort: 8000
}
}
// ...
}
}
Frontend calling Backend:¶
import requests
import os
# Use internal DNS name
BACKEND_URL = os.environ.get('BACKEND_URL', 'http://ca-backend')
@app.route('/api/data')
def get_data():
# Call internal backend service
response = requests.get(f'{BACKEND_URL}/api/items')
return response.json()
With Dapr Service Invocation¶
Enable Dapr for service discovery and invocation:
resource frontendApp 'Microsoft.App/containerApps@2023-05-01' = {
name: 'ca-frontend'
properties: {
configuration: {
dapr: {
enabled: true
appId: 'frontend'
appPort: 8000
}
}
// ...
}
}
import requests
# Dapr sidecar handles service discovery
DAPR_HTTP_PORT = 3500
@app.route('/api/data')
def get_data():
# Invoke backend via Dapr
response = requests.get(
f'http://localhost:{DAPR_HTTP_PORT}/v1.0/invoke/backend/method/api/items'
)
return response.json()
Benefits of Dapr¶
| Feature | Without Dapr | With Dapr |
|---|---|---|
| Service Discovery | Manual DNS | Automatic |
| Retries | Implement yourself | Built-in |
| Tracing | Manual | Automatic |
| mTLS | Configure yourself | Automatic |
Add explicit timeouts and retries
Even with internal networking or Dapr service invocation, enforce client-side timeouts, bounded retries, and idempotency to avoid cascading failures.
Portal view: Ingress blade¶

[Observed] The blade header reads <your-app-name> | Ingress with the subtitle Container App. The command bar exposes Refresh and Send us your feedback. A banner above the form notes that traffic is going to the latest revision and links to the revision management page. The form contains an Ingress checkbox in the checked state, followed by an Ingress traffic radio group with two options: Limited to Container Apps Environment and Accepting traffic from anywhere, with the second option selected. Below that, Ingress type shows HTTP selected and TCP shown but not selectable. Client certificate mode shows three radios: Ignore (selected), Accept, and Require. Transport is a dropdown showing the value Auto. Insecure connections is an unchecked checkbox. Target port shows the value 80. An Endpoint(s) row renders a full app FQDN. A collapsed Additional TCP ports section and an IP Restrictions section showing Allow all traffic (default) follow. Save and Discard buttons appear at the bottom of the form. The left navigation highlights Ingress under the Networking group.
[Inferred] The Ingress traffic radio option Limited to Container Apps Environment appears to map to the internal-only ingress configuration described in the Internal DNS section above, since both surfaces describe restricting reachability to the same Container Apps environment. The presence of an Endpoint(s) row on the same blade as the Ingress checkbox is consistent with the FQDN-based service discovery flow shown in the Internal Resolution Flow diagram.
[Not Proven] The screenshot does not show the panel or behavior that follows selecting Limited to Container Apps Environment, so the rendered shape of the resulting internal endpoint is outside the scope of this image. The Additional TCP ports section is collapsed and its contents are not visible. The IP Restrictions section header is visible but the rule editor is not.
See Also¶
- Ingress in Azure Container Apps
- Dapr Integration in Azure Container Apps
- Dapr Integration (Python recipe)
- VNet Integration
- Egress Control