Egress Control¶
Control outbound traffic from Container Apps.
Default Behavior¶
By default, Container Apps can access: - Public internet - Azure services via public endpoints - Resources in the same VNet (if VNet integrated)
Uncontrolled egress increases data exfiltration risk
Production workloads should define explicit outbound paths and approved destinations, especially when handling regulated or sensitive data.
Egress Strategy Comparison¶
| Strategy | Primary Goal | Trade-off | Typical Fit |
|---|---|---|---|
| Default outbound | Fast setup | Minimal governance | Dev/test environments |
| UDR + Azure Firewall | Domain/IP filtering and inspection | Higher complexity and cost | Regulated production workloads |
| NAT Gateway | Static outbound IP for allow-lists | No L7 filtering by itself | SaaS allow-list integrations |
User-Defined Routes (UDR)¶
Route outbound traffic through Azure Firewall or NVA:
flowchart TD
subgraph VNet [Virtual Network]
subgraph Subnet [CAE Subnet]
APP[Container App]
end
subgraph FWSubnet [AzureFirewallSubnet]
FW[Azure Firewall]
end
subgraph RT [Route Table]
R[0.0.0.0/0 -> Firewall IP]
end
end
subgraph Internet [Public Internet]
EXT[Public API]
end
APP -- 1. Outbound Request --> RT
RT -- 2. Next Hop --> FW
FW -- 3. Policy Check --> EXT resource routeTable 'Microsoft.Network/routeTables@2023-05-01' = {
name: 'rt-containerapp'
location: location
properties: {
routes: [
{
name: 'default-route'
properties: {
addressPrefix: '0.0.0.0/0'
nextHopType: 'VirtualAppliance'
nextHopIpAddress: firewallPrivateIp
}
}
]
}
}
Azure Firewall Rules¶
Allow required outbound traffic:
NAT Gateway Architecture¶
flowchart TD
subgraph VNet [Virtual Network]
subgraph Subnet [CAE Subnet]
APP[Container App]
end
NGW[NAT Gateway]
PIP[Public IP Address]
end
subgraph Internet [Public Internet]
EXT[Public Dependency]
end
APP -- 1. Outbound Traffic --> NGW
NGW -- 2. Source NAT (PIP) --> EXT resource firewallPolicy 'Microsoft.Network/firewallPolicies@2023-05-01' = {
name: 'fw-policy'
properties: {
sku: { tier: 'Standard' }
}
}
Azure Firewall Rules¶
Allow required outbound traffic:
resource firewallPolicy 'Microsoft.Network/firewallPolicies@2023-05-01' = {
name: 'fw-policy'
properties: {
sku: { tier: 'Standard' }
}
}
resource appRuleCollection 'Microsoft.Network/firewallPolicies/ruleCollectionGroups@2023-05-01' = {
parent: firewallPolicy
name: 'container-apps-rules'
properties: {
priority: 100
ruleCollections: [
{
ruleCollectionType: 'FirewallPolicyFilterRuleCollection'
name: 'allow-external-apis'
priority: 100
action: { type: 'Allow' }
rules: [
{
ruleType: 'ApplicationRule'
name: 'allow-jsonplaceholder'
protocols: [{ protocolType: 'Https', port: 443 }]
targetFqdns: ['jsonplaceholder.typicode.com']
sourceAddresses: ['10.0.0.0/23']
}
]
}
]
}
}
NAT Gateway for Static Outbound IP¶
Assign static IP for outbound traffic:
resource natGateway 'Microsoft.Network/natGateways@2023-05-01' = {
name: 'nat-containerapp'
location: location
sku: { name: 'Standard' }
properties: {
publicIpAddresses: [{ id: publicIp.id }]
}
}
resource subnet 'Microsoft.Network/virtualNetworks/subnets@2023-05-01' = {
name: 'snet-containerapp'
properties: {
addressPrefix: '10.0.0.0/23'
natGateway: { id: natGateway.id }
}
}
Combine NAT and firewall when needed
Use NAT Gateway for predictable source IP and Azure Firewall for destination governance when both compliance and partner allow-list requirements exist.
Verify Outbound IP¶
import requests
@app.route('/api/my-ip')
def my_ip():
# Use standard service to verify public outbound IP
response = requests.get('https://api.ipify.org?format=json')
return response.json() # Returns NAT Gateway's public IP
Required Outbound Dependencies¶
If you restrict egress and pull application images from Azure Container Registry (ACR) by using managed identity, allow the dependency categories that support both token acquisition and image download.
| Service Tag / Dependency | Port | When Required |
|---|---|---|
AzureActiveDirectory | 443 | Required when the container app uses managed identity to obtain an access token for ACR. |
ACR login server | 443 | Required for the registry endpoint (for example, <registry-name>.azurecr.io) unless you use a private endpoint for the registry. |
Storage.<Region> | 443 | Required for ACR-backed image layer downloads from regional storage. |
MicrosoftContainerRegistry | 443 | Required for Microsoft-managed system container dependencies in the environment. |
AzureContainerRegistry | 443 | Required when pulling images from ACR without a private endpoint. When using a private endpoint for ACR, this tag is not required. |
AzureFrontDoor.FirstParty | 443 | Required as a dependency of Microsoft Container Registry. |
When using Azure Firewall application rules instead of (or in addition to) NSG service tags, allow these FQDNs for managed identity token acquisition:
| FQDN | When Required |
|---|---|
login.microsoftonline.com | Token issuance for managed identity |
*.login.microsoftonline.com | Regional token endpoints |
login.microsoft.com | Primary Microsoft login endpoint |
*.login.microsoft.com | Alternative login endpoints |
*.identity.azure.net | Managed identity metadata |
Use service tags where Azure provides them, and use private endpoints or FQDN-aware firewall rules for registry-specific destinations.
flowchart TD
APP[Container App] --> FW[Firewall / NSG]
FW --> AAD[Microsoft Entra ID<br/>AzureActiveDirectory token]
FW --> MCR[Microsoft Container Registry<br/>System containers]
FW --> ACR[Azure Container Registry<br/>Application image]
ACR --> STG[Storage.<Region><br/>Image layers] Private ACR does not remove all outbound requirements
Even when ACR uses a private endpoint, managed identity image pulls still require outbound access to AzureActiveDirectory on port 443 so the platform can acquire a token.
Also keep DNS to 168.63.129.16:53 available; blocking platform DNS breaks name resolution for these dependencies.
For the failure symptoms and validation steps, see Image Pull Failure.