Background
Sections
IntroductionFoundations1. Resource Hierarchy2. Resource Manager3. Identity and RBAC4. Regions and Availability5. Naming and TaggingVirtual Machines1. What and Why2. Core Concepts3. Architecture4. Getting Started5. Deployment6. Integrations7. Production8. Interview Questions9. Glossary and CheatsheetVirtual Network1. What and Why2. Core Concepts3. Architecture4. Getting Started5. Deployment6. Integrations7. Production8. Interview Questions9. Glossary and CheatsheetBlob Storage1. What and Why2. Core Concepts3. Architecture4. Getting Started5. Deployment6. Integrations7. Production8. Interview Questions9. Glossary and CheatsheetAzure SQL Database1. What and Why2. Core Concepts3. Architecture4. Getting Started5. Deployment6. Integrations7. Production8. Interview Questions9. Glossary and CheatsheetAzure Kubernetes Service1. What and Why2. Core Concepts3. Architecture4. Getting Started5. Deployment6. Integrations7. Production8. Interview Questions9. Glossary and CheatsheetAzure Container Registry1. What and Why2. Core Concepts3. Architecture4. Getting Started5. Deployment6. Integrations7. Production8. Interview Questions9. Glossary and CheatsheetMicrosoft Entra ID1. What and Why2. Core Concepts3. Architecture4. Getting Started5. Deployment6. Integrations7. Production8. Interview Questions9. Glossary and CheatsheetAzure RBAC1. What and Why2. Core Concepts3. Architecture4. Getting Started5. Deployment6. Integrations7. Production8. Interview Questions9. Glossary and CheatsheetAzure Functions1. What and Why2. Core Concepts3. Architecture4. Getting Started5. Deployment6. Integrations7. Production8. Interview Questions9. Glossary and CheatsheetAPI Management1. What and Why2. Core Concepts3. Architecture4. Getting Started5. Deployment6. Integrations7. Production8. Interview Questions9. Glossary and CheatsheetAzure App Configuration1. What and Why2. Core Concepts3. Architecture4. Getting Started5. Deployment6. Integrations7. Production8. Interview Questions9. Glossary and CheatsheetAzure Machine Learning1. What and Why2. Core Concepts3. Architecture4. Getting Started5. Deployment6. Integrations7. Production8. Interview Questions9. Glossary and CheatsheetAzure Monitor1. What and Why2. Core Concepts3. Architecture4. Getting Started5. Deployment6. Integrations7. Production8. Interview Questions9. Glossary and CheatsheetAzure AI Foundry1. What and Why2. Core Concepts3. Architecture4. Getting Started5. Deployment6. Integrations7. Production8. Interview Questions9. Glossary and Cheatsheet

6. Integrations

10 min read

ACR is the most-depended-upon service in Azure's compute category and the least self-sufficient: on its own it does nothing. This page covers the services it's almost always wired to, and — more usefully — the glue, which in Azure is nearly always one of two mechanisms.

The two mechanisms that answer most questions

Managed identity + a role assignment. The keyless way one Azure resource authenticates to another. For ACR the role is almost always AcrPull (for a runtime) or AcrPush (for a builder), assigned at the registry's resource ID. If you find yourself creating an imagePullSecret, a service principal password, or enabling the admin user, you have skipped this mechanism and should go back.

Private endpoint + Private DNS zone. The way one Azure resource reaches ACR without traversing the public internet. ACR exposes exactly one sub-resource — registry — and the zone name is fixed at privatelink.azurecr.io. On a geo-replicated registry the private endpoint creates one A record per replica region plus the login server record, and if you've enabled dedicated data endpoints there are data records too. Every private-endpoint failure in ACR is a DNS failure: the zone isn't linked to the consuming VNet, or an on-prem resolver isn't forwarding.

Pairs with Why The glue
Azure Kubernetes Service AKS pulls every image it runs from here az aks update --attach-acr = an AcrPull role assignment to the kubelet identity. No imagePullSecret
Azure Container Apps Same, for the serverless container runtime User- or system-assigned identity on the Container App + AcrPull; set the registry identity in the app's registries config
App Service / Functions (containers) Runs a custom image System-assigned identity + AcrPull, then set acrUseManagedIdentityCreds on the site
Azure Container Instances One-off container runs Managed identity + AcrPull (system-assigned works; user-assigned is more manageable)
Microsoft Entra ID Who may pull and push Azure RBAC data-plane roles on the registry resource; the token exchange in Architecture
Key Vault Customer-managed encryption keys; signing keys for Notation User-assigned identity with Key Vault Crypto Service Encryption User; configured at registry creation
Microsoft Defender for Cloud Vulnerability scanning of pushed images Enable the containers plan at subscription scope; findings surface per-image, and for AKS, per running workload
Azure Monitor / Log Analytics Who pulled what, and when Diagnostic setting → ContainerRegistryLoginEvents + ContainerRegistryRepositoryEvents + AllMetrics
Event Grid React to pushes and deletes System topic on the registry emitting Microsoft.ContainerRegistry.ImagePushed / ImageDeleted / ChartPushed
GitHub Actions / Azure Pipelines Build and push Workload identity federation (OIDC) + AcrPush. Never a client secret
Virtual Network + Private Link Keep the pull path off the internet Private endpoint (sub-resource registry) + privatelink.azurecr.io zone linked to every consuming VNet
Azure Policy Enforce the registry's shape across the estate Built-in policies for admin user, public network access, CMK, and private endpoints
Azure Machine Learning Environments are built into a registry AML workspaces attach an ACR; custom environments are built as images and stored there

[Image Prompt: 2D minimalistic hub-and-spoke diagram with Azure Container Registry at the centre connected to AKS, Container Apps, App Service, Key Vault, Microsoft Defender for Cloud, Azure Monitor, Event Grid, and GitHub Actions, with each edge labelled by its glue mechanism such as managed identity plus AcrPull or private endpoint, flat design, clean vector art style, white background]

AKS — the pairing that matters most

The canonical wiring, and the one interviews ask about:

az aks update -n aks-prod -g rg-platform --attach-acr acrplatformprod

That single command is doing something worth understanding: it creates an AcrPull role assignment on the registry, for the cluster's kubelet identity (the user-assigned identity AKS uses on the nodes, not the cluster's control-plane identity). Nothing is written into Kubernetes. There is no secret, no imagePullSecret, and nothing to rotate. When a pod's image reference points at acrplatformprod.azurecr.io/..., the kubelet's Azure credential provider performs the Entra token exchange described in Architecture and pulls.

The Terraform equivalent — preferable, because the CLI command's effect is invisible to your state:

resource "azurerm_role_assignment" "aks_acr_pull" {
  scope                = azurerm_container_registry.this.id
  role_definition_name = "AcrPull"
  principal_id         = azurerm_kubernetes_cluster.this.kubelet_identity[0].object_id
}

When it doesn't work, it's one of four things, in order of frequency:

  1. The role assignment is on the wrong identity — the cluster identity instead of the kubelet identity. Symptom: 401 unauthorized on pull.
  2. DNS. The private DNS zone isn't linked to the cluster's VNet, so nodes resolve the public IP and time out. Symptom: ImagePullBackOff with a timeout, not a 401. Diagnose from a node: nslookup acrplatformprod.azurecr.io should return a private address.
  3. Egress firewall. *.azurecr.io is allowed but the layer-blob redirect to Microsoft-managed storage is not. Symptom: manifests resolve, layers hang. Fix: enable dedicated data endpoints and allow-list <registry>.<region>.data.azurecr.io.
  4. RBAC propagation. Role assignments can take a couple of minutes. Symptom: it works if you wait. Not a bug.

Cross-subscription and cross-tenant AKS→ACR both work — a role assignment doesn't care about subscription boundaries within a tenant, and cross-tenant requires the identity to be granted in the registry's tenant. What doesn't exist is an ECR-style resource policy, so the grant is always made on the registry side by someone with Owner/User Access Administrator.

Container Apps, App Service, and Functions

The same shape with different configuration surfaces:

# Container Apps — user-assigned identity is the manageable choice
az containerapp registry set \
  -n app-api -g rg-platform \
  --server acrplatformprod.azurecr.io \
  --identity /subscriptions/.../userAssignedIdentities/id-app-api

# App Service / Functions on a custom container
az webapp identity assign -n app-api -g rg-platform
az role assignment create --assignee <principal-id> --role AcrPull --scope <registry-id>
az webapp config set -n app-api -g rg-platform --generic-configurations '{"acrUseManagedIdentityCreds": true}'

The App Service trap: if you created the app pointing at ACR before assigning the identity, the portal may have stored the admin-user credentials in app settings (DOCKER_REGISTRY_SERVER_PASSWORD). Switching to managed identity means deleting those settings as well as setting the flag — otherwise the old credentials keep working and mask the fact that the identity path was never tested.

For Container Apps and Functions on the Consumption plan, a private-endpoint-only registry needs the runtime to have VNet integration. A serverless runtime with no VNet cannot reach a private registry, and this constraint kills more designs than any other in this topic.

Defender for Cloud — scanning

Vulnerability scanning is not an ACR feature; it's a Microsoft Defender for Cloud feature (the containers plan) that watches the registry. Enable it at subscription scope and it scans images on push and on a recurring schedule ⚠️ verify current scan cadence and pricing model.

Two things worth knowing:

  • Registry findings and runtime findings are different views. Defender reports vulnerable images in the registry and vulnerable images actually running in AKS. The second list is the one to act on first — an unused vulnerable image in a repository is a cleanup task, not an incident.
  • Scanning needs to reach the registry. On a fully private registry, ensure Defender's access path is configured; network_rule_bypass_option = "AzureServices" exists partly for this.

For blocking rather than reporting, the enforcement point is Kubernetes admission, not the registry: Azure Policy for AKS (Gatekeeper) with a constraint that only permits images from your registry, or a signature-verification admission controller (Notation + Ratify) that rejects unsigned images.

Event Grid — reacting to pushes

An Event Grid system topic on the registry emits events you can route:

az eventgrid system-topic create \
  -n egst-acr -g rg-platform \
  --source $(az acr show -n acrplatformprod -g rg-platform --query id -o tsv) \
  --topic-type Microsoft.ContainerRegistry.Registries -l uksouth

az eventgrid system-topic event-subscription create \
  -n on-image-pushed -g rg-platform --system-topic-name egst-acr \
  --included-event-types Microsoft.ContainerRegistry.ImagePushed \
  --endpoint <function-or-webhook-url>

Useful patterns: trigger a deployment when a specific repository gets a new tag; notify a channel; kick off a supply-chain step like signing or SBOM generation. Webhooks are the simpler, older mechanism and are regional on a geo-replicated registry — handy when you want a per-region reaction, awkward when you want exactly one.

Cache rules — putting upstream registries inside your boundary

The clean answer to Docker Hub rate limits and to air-gapped-ish environments:

# Optional: credentials for an authenticated upstream, stored in Key Vault
az acr credential-set create -r acrplatformprod -n dockerhub \
  --login-server docker.io \
  --username-id  <kv-secret-uri-for-username> \
  --password-id  <kv-secret-uri-for-password>

az acr cache create -r acrplatformprod -n dockerhub-nginx \
  --source-repo docker.io/library/nginx \
  --target-repo dockerhub/nginx \
  --cred-set dockerhub

Consumers then pull acrplatformprod.azurecr.io/dockerhub/nginx:1.27, and ACR fetches from upstream on the first request and serves locally thereafter. ⚠️ Verify which tiers support cache rules and the current CLI surface against Azure docs.

The caveat worth stating: a cache is not a mirror. It fetches on demand, so an upstream outage still breaks the first pull of an image you've never fetched. If you need genuine independence, az acr import the images you depend on.

ACR Tasks — building without a build agent

The integration people forget. az acr build builds in Azure; a base-image-update trigger rebuilds automatically when the base image changes:

az acr task create \
  -r acrplatformprod -n api-build \
  --context https://github.com/org/repo.git#main \
  --file Dockerfile \
  --image api:{{.Run.ID}} \
  --base-image-trigger-enabled true \
  --commit-trigger-enabled true \
  --assign-identity [system]

Combined with an Event Grid subscription on ImagePushed, this gives you a patch-the-base → rebuild → redeploy loop with no CI runner involved. It is the cheapest CVE remediation available on the platform, and it's the strongest argument for putting your base images in ACR rather than pulling them from MCR at build time.

Tasks authenticate with their own managed identity, so a task that pushes needs AcrPush and a task that pulls a private base image needs AcrPull on the source registry.

Designing it into an architecture

The default production shape, assembled from the above:

  • One Premium registry per environment, geo-replicated to every region you deploy in.
  • Public network access disabled, private endpoints in each consuming VNet, one privatelink.azurecr.io zone linked to all of them, dedicated data endpoints enabled and allow-listed in the egress firewall.
  • Every runtime authenticates with a managed identity holding AcrPull. Admin user disabled and denied by policy.
  • The build pipeline holds AcrPush via workload identity federation, and nothing else.
  • Promotion between environments is az acr import by digest, not a rebuild.
  • Defender for Cloud scans; Azure Policy for AKS restricts admission to your registries.
  • Diagnostic settings to a Log Analytics workspace, retained long enough to answer "who pulled this."

Next: Production →

← Back to the Azure Container Registry overview · ← Previous: Deployment