In almost every Azure project I work on, Azure Container Registry sits at the centre of the workloads. AKS, Azure Container Apps and CI/CD pipelines all pull from it. Even so, tenant reviews keep turning up ACR instances that are publicly exposed for no reason, run on static credentials or have weak retention settings. Securing Azure Container Registry for production means going well past the defaults, and that covers identity, network, data loss protection and governance.

Disabling the admin user moves all access to Entra ID and managed identities

The first thing I look at in any ACR is whether the admin user is still enabled. This built-in account works with static access keys, and it is still a common cause of credential sprawl and possible compromise, particularly when the keys end up hardcoded in pipelines or handed to developers "just for convenience." Fixing it is easy: disable the admin user (Azure Portal → Container Registries → your registry → Access keys). From then on, all access should go through Entra ID, using managed identities wherever you can. For AKS or Azure Container Apps, give the workload managed identity the "AcrPull" role (plus "AcrPush" if it needs it) at registry scope. You can do that in the Azure Portal under Access control (IAM) or with the Azure CLI:

# Azure CLI, sign in as Owner or User Access Administrator
az acr update --name <acr-name> --admin-enabled false
az role assignment create --assignee <managed-identity-id> --role AcrPull --scope $(az acr show --name <acr-name> --query id -o tsv)

If CI pipelines have to run with service principals, use scope maps so they only get the access they need, for example repository-specific tokens for push or pull. Microsoft describes this in its best practices for Azure Container Registry, and by now it is simply the expected baseline.

Private endpoints replace public network access entirely

With ACR Premium you can restrict the registry completely to your Azure VNet. That removes its public footprint and fits current compliance requirements. In practice you create a Private Endpoint (Azure Portal → Container Registry → Networking → Private Endpoint connections) and then set Public network access to Disabled. Keep in mind that build agents, CI/CD runners and AKS clusters have to sit in the same VNet or be connected through VNet peering. A missing route or DNS entry here is one of the most frequent reasons for connectivity problems.

The Mermaid diagram below shows the flow I recommend, with managed identity, private endpoint and identity-based access for AKS or CI.

flowchart TD
  DevOps["DevOps Pipeline"] --> CIUser["CI Service Principal or MI"]
  CIUser --> Token["ACR token (scope map)"]
  AKS["AKS or Container App"] --> MI["Managed Identity"]
  MI --> AcrPull["Role: AcrPull"]
  AcrPull --> ACR["ACR (Private Endpoint)"]
  Token --> ACR

Figure: Secure access to Azure Container Registry via private endpoint and managed identities.

If DNS for Private Endpoints is giving you trouble, I've written about the usual pitfalls here: /blog/azure-private-endpoints-dns-common-mistakes.

Soft delete and retention protect against accidental deletion

Accidental deletion gets overlooked far too often. A pipeline or admin script removes the wrong image, and important artifacts are gone. The Premium SKU lets you turn on retention and soft delete (Azure Portal → Container Registry → Data management → Soft delete & retention). With that in place you can restore deleted images within the time window you defined, which helps a lot when something goes wrong.

Pro tip: A short retention window still beats having none. I've watched this one setting save whole teams after a rushed cleanup script deleted far more than it should have.

These features are mature enough now that I treat them as part of the baseline rather than an optional extra.

Defender for Containers scans every image for vulnerabilities

A secure Azure Container Registry also needs Defender for Containers (previously Defender for Container Registries). Once it's on, every new or updated image is scanned for CVEs automatically, and you get security recommendations you can act on. You enable it in Defender for Cloud → Environment settings → Container Registry, as long as you have the Defender for Containers licence and at least the Security Reader role on the registry.

The findings go straight into Secure Score, and you can connect them to your SOC processes. For more practical guidance, take a look at the Microsoft Container Registry best practices.

Azure Policy enforces ACR standards across all registries

Once an Azure environment gets large, you can't run it without Azure Policy. For ACR, you can use it to:

  • Require Premium SKU and private endpoint for all new registries
  • Make sure the admin user stays disabled
  • Enforce soft delete and retention policies
  • Keep network and security settings the same across all registries

You'll find these definitions in the Azure Policy catalog (Azure Portal → Policy → Definitions → Azure Container Registry). Assign them at management group level to cover as much as possible. That stops shadow registries from appearing and catches accidental misconfiguration.

I standardize early and review often

Securing Azure Container Registry is no longer something you set up once and forget. The technical basics (admin user off, Entra ID everywhere, private endpoints, soft delete) are easy enough. Real security, though, depends on enforced policy and continuous monitoring through Defender and Log Analytics. Time and again I've seen that organizations which standardize from day one, and actually audit their settings, avoid the nasty surprises. Even experienced teams sometimes let DNS, network or token controls slip. If you want an ACR platform you can rely on and audit, make these settings your default and not just a box to tick for compliance.