# Azure Container Apps network-design guide: VNet integration, internal environment, Private Endpoint, WAF, and egress lockdown

> An implementation guide to designing Azure Container Apps networking at production quality. Faithful to the official Microsoft Learn docs, it explains the dedicated subnet (/27) of a workload-profile environment, the internal environment and External/Internal, going private with Private Endpoint, fronting with Application Gateway + WAF, egress lockdown via UDR + Azure Firewall, and DNS (168.63.129.16).

- Published: 2026-06-26
- Author: 友田 陽大
- Tags: Azure, Container Apps, ネットワーク, セキュリティ, VNet, WAF, インフラ, アーキテクチャ設計
- URL: https://tomodahinata.com/en/blog/azure-container-apps-networking-vnet-private-endpoint-waf-egress-guide
- Category: Azure Container Apps in production
- Pillar guide: https://tomodahinata.com/en/blog/azure-container-apps-production-guide

## Key points

- A production network defaults to a workload-profile environment + a dedicated subnet (minimum /27). It supports UDR, NAT Gateway, and Private Endpoint. Consumption only (legacy) is /23 and doesn't support UDR/NAT.
- Accessibility is chosen per Environment: External (public IP) or Internal (internal LB IP only). An Internal environment always has public network access Disabled, becoming the foundation for Private Endpoint operation.
- The standard for defense in depth: an internal environment + Application Gateway (WAF) in front + UDR to route all egress through Azure Firewall. The network type can't be changed after creation, so decide it first.
- The subnet is environment-dedicated (can't be shared with other services). Custom DNS forwards unresolved queries to 168.63.129.16, and don't block this address or login.microsoft.com in the NSG/firewall.
- External TCP Ingress requires a VNet. Outbound IPs can change, so if you need fixed egress, use NAT Gateway (workload-profile environment only).

---

What's always asked in enterprise projects is **networking and security.** "Don't expose it externally, keep it closed within the VNet," "place a WAF in front," "control outbound with a firewall" — without answering these, it doesn't go to production.

This article explains Azure Container Apps' (ACA) **production network design**, faithful to the [Microsoft Learn networking documentation](https://learn.microsoft.com/en-us/azure/container-apps/networking). I've run a [multi-layer API Gateway→NLB→ALB→ECS configuration](/blog/aws-ecs-fargate-networking-alb-service-connect-vpc-guide) in production on AWS and designed [WAF defense in depth](/blog/waf-defense-in-depth-aws-waf-cloud-armor-owasp-guide). The idea of "build the trust boundary with the network" is isomorphic on Azure. For ACA as a whole, see the [Azure Container Apps production-operations guide](/blog/azure-container-apps-production-guide).

---

## The big premise: the environment has the VNet

> Azure Container Apps operates in the context of an environment, which runs its own virtual network. (— [Networking in an Azure Container Apps Environment](https://learn.microsoft.com/en-us/azure/container-apps/networking))

Networking is **per environment, not per app.** Apps in the same environment share a VNet. The three things to decide first in design are — **environment type, VNet type, and accessibility level.** And the decisive constraint:

> After you create an environment with either the default Azure network or an existing virtual network, you can't change the network type.

**The network type can't be changed after creation.** The initial design is irreversible, so be careful here.

---

## Environment type and subnet size

| Environment type | Supported plans | Features | Minimum subnet |
|-----------|----------|------|:------------:|
| **Workload profile (default)** | Consumption, Dedicated | Supports **UDR, NAT Gateway, Private Endpoint** | `/27` |
| **Consumption only (legacy)** | Consumption | **Doesn't support** UDR, NAT Gateway, remote gateway, etc. | `/23` |

If you want to control the network in production, it's a **workload-profile environment, the only choice.** UDR (user-defined routes), NAT Gateway, and Private Endpoint — the keys to egress control and going private — are available only here.

> The subnet must be **dedicated to the ACA environment**. `you need to provide a subnet that's dedicated exclusively to the Container Apps environment that you deploy. This subnet isn't available to other services.` — carve out a dedicated subnet not shared with other services.

---

## Accessibility: External and Internal

At environment creation, choose whether to expose it or keep it internal.

| Level | Description |
|-------|-----|
| **External** | Has a public IP (an external-facing virtual IP) and can receive requests from the internet. |
| **Internal** | Has no public endpoint and is mapped to an internal IP (an Azure internal load balancer). Issued from a **private IP** of the VNet. |

And the behavior of `public network access` depends on the virtual IP configuration.

| Virtual IP | Configurable public network access |
|-------|-------------------------------|
| External | `Enabled` / `Disabled` (changeable after creation) |
| **Internal** | **`Disabled` only** (can't change to internet receiving) |

> To create a Private Endpoint, `To create private endpoints in your Container Apps environment, you must set public network access to Disabled.` — you must **set public network access to Disabled.** Since an Internal environment always has this Disabled, it's a natural foundation for Private Endpoint operation.

---

## Defense-in-depth architecture: the production standard

Let me put the "lockdown" configuration the official docs show into a practical form.

```text
                        [Internet]
                            │
              ┌─────────────▼──────────────┐
              │  Application Gateway + WAF   │  ← OWASP対策・L7防御・公開接点はここだけ
              └─────────────┬──────────────┘
                            │ (VNet内のプライベート通信)
      ┌─────────────────────▼─────────────────────┐
      │  Internal ACA Environment（専用サブネット /27） │
      │   ├─ public-api      (External Ingress: 環境内)  │
      │   ├─ order-worker    (Ingress無し / Service Bus駆動)│
      │   └─ nightly-report  (Schedule Job)               │
      └─────────────────────┬─────────────────────┘
                            │ egress
              ┌─────────────▼──────────────┐
              │  UDR → Azure Firewall        │  ← 全アウトバウンドを検査・許可リスト制御
              └─────────────┬──────────────┘
                            ▼
                  許可した宛先（ACR/Key Vault/外部API）のみ
```

This is exactly the official "environment security" guidance.

> - Create your internal Container Apps environment in a workload profile environment.
> - Integrate Container Apps with Application Gateway.
> - Configure a UDR to route all traffic through Azure Firewall. (— [networking](https://learn.microsoft.com/en-us/azure/container-apps/networking))

### ① The front: Application Gateway + WAF

Unify the public contact point into **Application Gateway (with WAF)**, make the ACA environment Internal, and don't expose it directly to the internet. The WAF blocks OWASP Top 10 (SQLi, XSS, etc.). This is the AWS "ALB + AWS WAF" replaced with `Application Gateway + WAF` on Azure ([the design philosophy of WAF defense in depth](/blog/waf-defense-in-depth-aws-waf-cloud-armor-owasp-guide)).

### ② Going private: Private Endpoint / Front Door

- **Private Endpoint**: expose the ACA environment with a private IP in the VNet and access it without going through the internet. Use it with public network access Disabled.
- **Azure Front Door**: `Connect directly from Azure Front Door to a container app by using a private link instead of the public internet.` — connect from Front Door via Private Link and place a global edge/CDN/WAF in front.

### ③ Egress lockdown: UDR + Azure Firewall

Detour all outbound through **Azure Firewall with UDR** and block communication to anything other than allowed destinations (ACR, Key Vault, specific external APIs). The key to data-exfiltration countermeasures. This is possible **only in a workload-profile environment.**

---

## Outbound IPs and NAT Gateway

The requirement of "I want to register on an external API's IP allowlist, I want a fixed egress IP" isn't rare. There's a caveat here.

> Outbound IPs might change over time. Using Azure NAT Gateway or another proxy for outbound traffic from a Container Apps environment is supported only in a workload profile environment. (— [networking](https://learn.microsoft.com/en-us/azure/container-apps/networking))

**The default outbound IP can change.** To fix it, secure a stable egress IP with **NAT Gateway** (workload-profile environment only). It's a pattern that becomes essential in business integration where "the partner's API requires IP-allowlist registration."

---

## Ingress and protocols: the networking-perspective essentials

- **The public ports are 80/443 only** (HTTP/HTTPS). HTTPS is TLS-terminated, with 80→443 auto-redirect.
- **An Envoy edge proxy** handles TLS termination and routing. It auto-detects HTTP/1.1 and HTTP/2 and upgrades.
- **External TCP Ingress is a bit special**: `External TCP ingress is only supported for Container Apps environments that use a virtual network.` — external TCP exposure requires a VNet.
- **Path-based routing**: within one environment, you can route to multiple container apps by path.
- **IP restriction, mTLS (client certificate), session affinity, and CORS** are enabled in Ingress settings.

---

## The DNS pitfall

The most common trouble with VNet integration is DNS. In an environment using custom DNS, forgetting this makes **image pulls and management communication fail.**

> Azure recursive resolvers uses the IP address `168.63.129.16` to resolve requests. (— [troubleshooting](https://learn.microsoft.com/en-us/azure/container-apps/troubleshooting))

- If you use a custom DNS server, configure it to **forward unresolved queries to `168.63.129.16`.**
- **Don't block `168.63.129.16`** in the NSG or firewall.
- If you use a managed identity, ensure **reachability to the token endpoint `login.microsoft.com` (or `<REGION>.login.microsoft.com`).**
- If you use a private registry like ACR, ensure its FQDN can be resolved and reached.

When tightening egress with UDR + Firewall, don't forget to **put these required destinations in the allowlist.**

---

## Layering with NSG

A VNet-integrated environment can attach an **NSG (network security group)** to the subnet to control inbound/outbound even more finely. Respecting the official required rules (management communication, DNS, the internal port for probes, etc.), block communication unneeded for the business. Not blocking `168.63.129.16` and the communication needed for platform management is the trick to not breaking operations.

---

## The trap of not being able to delete the environment

Trying to delete a VNet-integrated environment and it stays at `provisioningState: ScheduledForDelete` without disappearing — this is common. The cause is **the associated VNet remaining.** The procedure: identify the VNet from the environment's `infrastructureSubnetId`, manually delete the VNet, then delete the environment (details in the [troubleshooting guide](/blog/azure-container-apps-troubleshooting-revision-failed-exit-code-137-probes-guide)).

---

## Design checklist

- [ ] Choose a **workload-profile environment** (essential if you need UDR/NAT/Private Endpoint). The subnet is **dedicated, minimum /27.**
- [ ] Decide **External/Internal** per public requirement (**can't change after creation**).
- [ ] Unify the public contact point into **Application Gateway + WAF**, and make the ACA environment Internal.
- [ ] If going private, **Private Endpoint** (public network access=Disabled) or Front Door + Private Link.
- [ ] Lock down outbound with **UDR + Azure Firewall**. Fixed egress IP with **NAT Gateway.**
- [ ] **DNS**: custom DNS forwards to `168.63.129.16`, allow `login.microsoft.com` and the registry FQDN.
- [ ] Layer the subnet with an **NSG** (don't block platform-required communication).

---

## Summary

ACA's networking has the structure of **environment = VNet = security boundary**, and production quality is decided by the "initial design" (**the type can't be changed later**). The enterprise standard is — on the foundation of a **workload-profile environment + dedicated subnet**, **Application Gateway (WAF) in front**, **go private with Internal + Private Endpoint**, and **egress lockdown with UDR + Firewall.** The thinking from designing AWS defense in depth ports straight into Azure's vocabulary.

For designing and building enterprise requirements including VNet integration, WAF, Private Endpoint, and egress control, [contact me](/contact). For production operations as a whole, see the [Azure Container Apps production-operations guide](/blog/azure-container-apps-production-guide).
