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

1. What and Why

8 min read

In one sentence: Azure Container Registry is a managed, regional, private OCI registry — an HTTPS endpoint named <yourname>.azurecr.io that stores container images and other OCI artifacts, authenticates callers with Microsoft Entra ID, and is billed per tier-day plus storage plus egress.

The problem before it existed

A container image isn't a file. It's a manifest — a small JSON document listing a config blob and an ordered set of compressed layer blobs, each addressed by its SHA-256 digest. To "have an image" somewhere, you need a service that can store those blobs, deduplicate them (because fifty images share the same Debian base layers), serve them concurrently to hundreds of machines, and tell you which of them a human-readable tag currently points at.

Before managed registries, teams ran the reference implementation themselves: the open-source registry:2 image, on a VM, behind a load balancer, with a storage backend, a TLS certificate they had to rotate, and an auth token server they usually skipped because it was hard. Three predictable things then happened. The certificate expired on a Saturday. The disk filled up, because the registry's garbage collector is a stop-the-world offline operation that nobody scheduled. And the "temporary" basic-auth password ended up committed to a Helm chart.

The analogy: ACR is a private Docker Hub with your organisation's name on it, an Azure login instead of a password, a firewall you control, and an invoice. Everything you already know about docker push and docker pull is unchanged — that's the point of standardising on a protocol. What changes is who owns the uptime, the identity, and the network boundary.

[Image Prompt: 2D minimalistic split diagram contrasting a self-hosted container registry where the team owns the VM, TLS certificate, storage, garbage collection, and auth server against Azure Container Registry where Microsoft owns those components and the team owns only the images and access policy, flat design, clean vector art style, white background]

Why a private registry, specifically

Three reasons, in the order teams actually encounter them.

Rate limits. Docker Hub applies pull-rate limits to anonymous and free authenticated traffic ⚠️ verify current thresholds against Docker's documentation. A Kubernetes cluster looks like one IP address to Docker Hub and pulls constantly during a rolling deployment, a node scale-out, or a node repair. The failure is a 429 mid-deployment, pods stuck in ImagePullBackOff, and an incident whose root cause is outside your control and outside your contract. This is the single most common reason organisations adopt a private registry, and it is a good one.

Boundary. Your application image contains your application. Even if the code isn't secret, the build is: the dependency set, the internal hostnames baked into config, the layer that copies in a schema. Public registries put that outside your control plane. A private registry with a private endpoint keeps the image, its transfer, and its access log inside the network you already govern.

Provenance. Once the registry is yours, you can enforce things: scan on push, block unsigned images at admission, make tags immutable so v1.2 cannot silently change, and answer "which build is running in prod, and what was in it" with a digest rather than a shrug.

Where it sits, and what it's confused with

ACR is in the compute category, but it behaves like a storage service with a compute-shaped API. Its distinguishing property is that almost nothing uses it directly and almost everything depends on it: AKS, Container Apps, App Service for Containers, Azure Functions on a custom image, Azure Machine Learning environments, Azure Batch container pools, and ACI all pull from it.

Confused with The difference in one line
Docker Hub Public, shared, rate-limited, and outside your boundary. Fine as an upstream; poor as your production pull path.
Microsoft Artifact Registry (mcr.microsoft.com) Microsoft's public registry for its own base images. Read-only to you; ACR's cache rules exist to bring copies of it inside your boundary.
GitHub Container Registry (ghcr.io) A real alternative when the whole supply chain is GitHub. You lose Azure private endpoints, Entra RBAC on the registry resource, and geo-replication.
Azure Artifacts NuGet/npm/Maven/PyPI packages, not OCI images. Adjacent problem, different service.
Blob Storage ACR stores its blobs in Microsoft-managed storage you never see. You cannot point ACR at your own storage account, and you should not build a registry on top of Blob Storage yourself.
Azure Container Instances (ACI) Runs a container. ACR stores the image it runs. Frequently confused purely because both abbreviate to three letters starting with AC.

The AWS analogue, and where it breaks

ACR is ECR. The transfer is good for the basics: private registry, cloud-IAM authentication instead of static passwords, per-GB storage plus egress billing, immutable tags, retention rules, and vulnerability scanning delivered by the cloud's security product rather than by the registry itself.

Four places the mental model breaks, and all four bite:

  1. The resource boundary is different. In ECR, the repository is the resource, with its own ARN and its own resource policy. In ACR, the registry is the resource and repositories are just path strings inside it — there is no Microsoft.ContainerRegistry/registries/repositories to assign a role at. If you assign AcrPull, you have granted pull on every repository in the registry.
  2. There is no resource-based policy. ECR repository policies let another account pull without anyone assigning a role in your account. Azure has no equivalent for ACR. Cross-boundary sharing is a role assignment to a principal (possibly a guest or a multi-tenant app), or a Premium token backed by a scope map, which is a generated password with a repository-scoped permission list.
  3. The name is global. myregistry.azurecr.io is a DNS name in a namespace shared by every Azure customer, so registry names collide across tenants exactly the way storage account names do. ECR's registry name is your account ID and can't collide.
  4. Geo-replication is a different shape. ECR asks you to configure replication between regional registries, each with its own URL. ACR Premium gives you one registry, one login server, many regional replicas, with Azure Traffic Manager routing each pull to the nearest healthy replica. You push once. It is genuinely nicer, and it is a Premium-only feature.

One more, smaller: ECR's login is get-login-password piped into docker login. ACR's az acr login performs an Entra token exchange and writes a short-lived refresh token into your Docker config, so the credential in the file expires (typically hours ⚠️ verify current lifetime) rather than being a static secret. Architecture traces that exchange.

When NOT to use ACR

  • Distributing a genuinely public image. Anonymous pull works (Standard and Premium), but you are then paying per-GiB storage and per-GB egress to serve the internet. That's what Docker Hub, ghcr.io, and MCR are for.
  • When you need per-repository RBAC with Entra identities. Azure RBAC's grain is the registry. Scope maps and tokens give you repository granularity but issue passwords, not identities — no Conditional Access, no managed identity, weaker audit. If strict per-team isolation is a hard requirement, one registry per boundary is the honest architecture, and registries are cheap enough at Basic/Standard to make that reasonable.
  • As a general-purpose artifact store. ORAS will push anything. Large datasets, build logs, and binaries belong in Blob Storage; language packages belong in Azure Artifacts. A registry's economics assume small, heavily-deduplicated, frequently-pulled layers.
  • Basic tier where a network requirement exists or is coming. Basic has no private endpoint support. The tier upgrade itself is online and non-destructive, but the architecture you built around a public endpoint is not.
  • As a backup. Geo-replication is a replica: a delete propagates. Enable the soft-delete policy ⚠️ verify current preview/GA status and retention window if you want a grace period, but do not confuse either with a backup product.
  • When the images are the wrong shape. A 12 GB single-layer image will be slow to push, slow to pull, expensive to store, and undeduplicated. The registry isn't the problem there; the Dockerfile is.

What you should be able to say after this page

  • What a registry actually stores (manifests, config blobs, layer blobs — all digest-addressed) and why a tag is not one of those things.
  • Three concrete reasons a private registry beats Docker Hub for a production pull path.
  • Where the ECR mental model transfers and the four places it doesn't.
  • At least three situations where reaching for ACR is the wrong call.

Next: Core Concepts →

← Back to the Azure Container Registry overview