Custom Domains and Certificates
Azure Container Apps supports custom hostnames and TLS certificates so you can serve production traffic on your own domain instead of the default azurecontainerapps.io endpoint. Managed certificates are validated through DigiCert and require public DNS reachability during issuance.
Architecture
flowchart TD
U[Client] --> DNS[Public DNS zone]
DNS --> INGRESS[Container Apps ingress]
DNS --> TXT[TXT record: asuid.<host>]
TXT --> ACA[Container Apps domain verification]
ACA --> DIGI[DigiCert domain validation]
DIGI --> CERT[Managed certificate issued]
flowchart TD
U[Client HTTPS request] --> CDNS[Custom domain DNS]
CDNS --> INGRESS[Container Apps ingress]
INGRESS --> APP[Container App revision]
Prerequisites
- Existing Container App:
$APP_NAME in $RG - Existing Container Apps environment:
$ACA_ENV_NAME - A public DNS zone you control for your domain
- Azure CLI with Container Apps extension
az extension add --name containerapp --upgrade
| Command | Why it is used |
az extension add ... | Installs or updates the Container Apps Azure CLI extension. |
Configure Custom Domain
- Get environment static IP (used for apex A record) and app default FQDN (used for subdomain CNAME):
export ENV_STATIC_IP=$(az containerapp env show \
--name "$ACA_ENV_NAME" \
--resource-group "$RG" \
--query "properties.staticIp" \
--output tsv)
export APP_FQDN=$(az containerapp show \
--name "$APP_NAME" \
--resource-group "$RG" \
--query "properties.configuration.ingress.fqdn" \
--output tsv)
| Command | Purpose |
export ENV_STATIC_IP=$(az containerapp env show --name "$ACA_ENV_NAME" --resource-group "$RG" --query "properties.staticIp" --output tsv) | Captures the environment static IP used for the apex-domain A record when binding a Python app to a custom domain. |
export APP_FQDN=$(az containerapp show --name "$APP_NAME" --resource-group "$RG" --query "properties.configuration.ingress.fqdn" --output tsv) | Captures the app's current ingress hostname so you can create the correct CNAME or validate the existing endpoint before cutover. |
- Get the domain verification value (
asuid) from the app:
export CUSTOM_DOMAIN_VERIFICATION_ID=$(az containerapp show \
--name "$APP_NAME" \
--resource-group "$RG" \
--query "properties.customDomainVerificationId" \
--output tsv)
| Command | Purpose |
export CUSTOM_DOMAIN_VERIFICATION_ID=$(az containerapp show --name "$APP_NAME" --resource-group "$RG" --query "properties.customDomainVerificationId" --output tsv) | Extracts the verification token that must be published in DNS before Container Apps will allow the custom domain to be attached. |
- Create DNS records (example with Azure DNS):
# Apex domain example: contoso.com -> environment static IP
az network dns record-set a add-record \
--resource-group "$DNS_RG" \
--zone-name "contoso.com" \
--record-set-name "@" \
--ipv4-address "$ENV_STATIC_IP"
# Subdomain example: www.contoso.com -> app FQDN
az network dns record-set cname set-record \
--resource-group "$DNS_RG" \
--zone-name "contoso.com" \
--record-set-name "www" \
--cname "$APP_FQDN"
# TXT verification record required by Container Apps
az network dns record-set txt add-record \
--resource-group "$DNS_RG" \
--zone-name "contoso.com" \
--record-set-name "asuid.www" \
--value "$CUSTOM_DOMAIN_VERIFICATION_ID"
| Command | Why it is used |
az network dns record-set ... | Creates or inspects networking resources such as VNets, DNS zones, routes, or private endpoints. |
- Add hostname to the Container App:
az containerapp hostname add \
--name "$APP_NAME" \
--resource-group "$RG" \
--hostname "www.contoso.com"
| Command | Why it is used |
az containerapp hostname add ... | Manages custom hostname bindings for ingress. |
Create Managed Certificate
Bind the hostname with a managed certificate. The certificate is automatically provisioned and validated using DNS.
az containerapp hostname bind \
--name "$APP_NAME" \
--resource-group "$RG" \
--hostname "www.contoso.com" \
--environment "$ACA_ENV_NAME" \
--validation-method CNAME
| Command | Why it is used |
az containerapp hostname bind ... | Manages custom hostname bindings for ingress. |
If you bring your own certificate instead of managed issuance, upload it to the environment with az containerapp env certificate upload and then bind it with az containerapp hostname bind --certificate <cert-name>.
Enforce HTTPS
Set ingress transport to HTTPS-only:
az containerapp ingress update \
--name "$APP_NAME" \
--resource-group "$RG" \
--transport auto \
--allow-insecure false
| Command | Why it is used |
az containerapp ingress update ... | Updates ingress settings on an existing Container App. |
Verification
az containerapp hostname list \
--name "$APP_NAME" \
--resource-group "$RG" \
--output table
az containerapp env certificate list \
--name "$ACA_ENV_NAME" \
--resource-group "$RG" \
--output table
| Command | Why it is used |
az containerapp hostname list ... | Manages custom hostname bindings for ingress. |
Then verify HTTPS from a client:
curl --verbose https://www.contoso.com/
Troubleshooting
- Managed certificate remains pending/failed: confirm the app hostname is publicly reachable and DNS records have propagated.
- DigiCert validation fails: verify
asuid.<host> TXT record value exactly matches the app verification ID. - CAA record blocks issuance: ensure your CAA policy allows DigiCert certificate issuance for your domain.
- HTTPS still not active: confirm hostname is bound to the expected certificate and certificate status is
Ready.
Advanced Topics
- Use apex + subdomain patterns together (A record for apex, CNAME for subdomain).
- Standardize DNS TTL strategy to reduce cutover delays during migration.
- Pair custom domains with WAF/CDN when you need global edge security and acceleration.
See Also
Sources