# Container Registry

Source: /azure/services/container-registry/

## Introduction

Azure Container Registry (ACR) is a managed, private OCI-compatible registry for storing container images and Helm charts.
It integrates natively with Azure Kubernetes Service, Azure Container Instances, and Azure App Service to streamline container-based application deployments.
ACR is commonly used to build, store, and manage container images as part of a continuous integration and deployment pipeline. For more information, see [What is Azure Container Registry?](https://learn.microsoft.com/en-us/azure/container-registry/container-registry-intro).

LocalStack for Azure provides a local environment for building and testing applications that make use of Azure Container Registry.
The supported APIs are available on our [API Coverage section](#api-coverage), which provides information on the extent of Container Registry's integration with LocalStack.

## Getting started

This guide walks you through creating a registry, logging in with Docker, pushing an image, and listing repositories.

Launch LocalStack using your preferred method. For more information, see [Introduction to LocalStack for Azure](/azure/getting-started/). Once the container is running, enable Azure CLI interception by running:

```bash
lstk az start-interception
```

This command points the `az` CLI away from the public Azure management REST API and toward the LocalStack for Azure emulator API.
To revert this configuration, run:

```bash
lstk az stop-interception
```

This reconfigures the `az` CLI to send commands to the official Azure management REST API.

### Create a resource group

Create a resource group to hold all resources created in this guide:

```bash
az group create --name rg-acr-demo --location westeurope
```

```bash title="Output"
{
  "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-acr-demo",
  "location": "westeurope",
  "name": "rg-acr-demo",
  "properties": { "provisioningState": "Succeeded" },
  "type": "Microsoft.Resources/resourceGroups"
}
```

### Create a container registry

Create a Basic-tier Azure Container Registry (Azure also offers Standard and Premium; limits differ by tier, as described in [Azure Container Registry SKU features and limits](https://learn.microsoft.com/en-us/azure/container-registry/container-registry-skus)):

```bash
az acr create \
  --name myacrdemo \
  --resource-group rg-acr-demo \
  --sku Basic \
  --admin-enabled true
```

```bash title="Output"
{
  "adminUserEnabled": true,
  "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-acr-demo/providers/Microsoft.ContainerRegistry/registries/myacrdemo",
  "location": "westeurope",
  "loginServer": "myacrdemo.azurecr.azure.localhost.localstack.cloud:4566",
  "name": "myacrdemo",
  "provisioningState": "Succeeded",
  "resourceGroup": "rg-acr-demo",
  "sku": { "name": "Basic", "tier": "Basic" },
  "type": "Microsoft.ContainerRegistry/registries"
...
}
```

### Log in with Docker

Authenticate the local Docker daemon to the registry using the Azure CLI:

```bash
az acr login --name myacrdemo
```

With Azure, `az acr login` is the documented way to authenticate Docker to your registry using your signed-in Microsoft Entra identity ([Push your first image to your Azure container registry using the Docker CLI](https://learn.microsoft.com/en-us/azure/container-registry/container-registry-get-started-docker-cli?tabs=azure-cli); for other auth options see [Authenticate with an Azure container registry](https://learn.microsoft.com/en-us/azure/container-registry/container-registry-authentication)). The emulator does not reproduce the full Azure identity flow, so the CLI may print an informational warning before confirming `Login Succeeded`. That is expected for LocalStack.

### Build and push an image

Create a minimal `Dockerfile` for the demo image:

```bash
cat > Dockerfile <<'EOF'
FROM alpine:latest
CMD ["echo", "Hello from LocalStack ACR!"]
EOF
```

Capture the registry login server returned by the emulator, then build and push the image using that address:

```bash
LOGIN_SERVER=$(az acr show --name myacrdemo --resource-group rg-acr-demo --query loginServer -o tsv)
docker build -t $LOGIN_SERVER/hello:v1 .
docker push $LOGIN_SERVER/hello:v1
```

Alternatively build directly within the emulated registry:

```bash
az acr build \
  --image hello:v1 \
  --registry myacrdemo \
  .
```

### Pull an image

Pull the image back from the registry to confirm it was pushed correctly:

```bash
docker pull $LOGIN_SERVER/hello:v1
```

### List repositories

List all image repositories stored in the registry:

```bash
az acr repository list --name myacrdemo
```

```bash title="Output"
[
  "hello"
]
```

### Check name availability

Check registry name availability against the management API. The following example assumes you already created `myacrdemo` above, so the response matches a name that is not available:

```bash
az acr check-name --name myacrdemo
```

```bash title="Output"
{
  "message": "The registry myacrdemo is already in use.",
  "nameAvailable": false,
  "reason": "AlreadyExists"
}
```

### Update registry settings

Disable the registry admin account (`az acr update` is the same command Azure documents for changing registry settings; see [`az acr update`](https://learn.microsoft.com/en-us/cli/azure/acr#az-acr-update)):

```bash
az acr update --name myacrdemo --resource-group rg-acr-demo --admin-enabled false
```

```bash title="Output"
{
  "adminUserEnabled": false,
  "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-acr-demo/providers/Microsoft.ContainerRegistry/registries/myacrdemo",
  "loginServer": "myacrdemo.azurecr.azure.localhost.localstack.cloud:4566",
  "name": "myacrdemo",
  "provisioningState": "Succeeded",
  "resourceGroup": "rg-acr-demo",
  "sku": { "name": "Basic", "tier": "Basic" },
  "type": "Microsoft.ContainerRegistry/registries"
...
}
```

### Show registry usage

Show current storage usage statistics for the registry:

```bash
az acr show-usage --name myacrdemo --resource-group rg-acr-demo
```

```bash title="Output"
{
  "value": [
    { "currentValue": 0, "limit": 10737418240, "name": "Size", "unit": "Bytes" },
    { "currentValue": 0, "limit": 2, "name": "Webhooks", "unit": "Count" },
    { "currentValue": 0, "limit": 100, "name": "ScopeMaps", "unit": "Count" },
    { "currentValue": 0, "limit": 100, "name": "Tokens", "unit": "Count" }
  ]
}
```

### Delete and verify

Delete the registry and remove the demo `Dockerfile` created earlier:

```bash
az acr delete --name myacrdemo --resource-group rg-acr-demo --yes
rm -f Dockerfile
```

## Features

- **Full CRUD lifecycle:** Create, read, update, and delete registry resources using the Azure CLI or ARM API.
- **Admin user management:** Enable or disable admin user access and retrieve admin credentials.
- **Name availability check:** Validate registry name uniqueness via `az acr check-name`.
- **Image push and pull:** Push and pull OCI-compliant container images using the standard Docker CLI.
- **In-registry builds:** Build images directly in the emulated registry using `az acr build`.
- **Repository listing:** List repositories and image tags stored in the registry.
- **Registry usage reporting:** Retrieve storage and limit usage via `az acr show-usage`.
- **Registry update:** Modify registry properties such as admin enabled and SKU.
- **Multiple SKUs accepted:** Basic, Standard, and Premium SKU names are accepted (all backed by the same local registry).

## Limitations

- **Geo-replication not supported:** Multi-region registry replication is not emulated.
- **ACR Tasks beyond basic build:** Task scheduling, triggers, and multi-step task workflows are mocked at the ARM level but not executed.
- **Private endpoints for ACR:** Private Link–based network isolation is not supported.
- **Webhook notifications:** Registry webhooks defined via the ARM API are stored but not fired on push events.
- **Content trust and quarantine:** Image signing and quarantine policies are not enforced.
- **Delete is not persisted:** `az acr delete` returns HTTP 200 and exits cleanly, but the registry record is not removed from the in-memory store in the current emulator version.

## Samples

The following sample demonstrates how to use Azure Container Registry with LocalStack for Azure:

- [Azure Container Instances, Key Vault, and Storage](https://github.com/localstack/localstack-azure-samples/blob/main/samples/aci-blob-storage/python/README.md)

## API Coverage


### Container Registry API coverage

Source service: `container-registry`. 63 of 73 tracked operations are implemented.

Service documentation: /azure/services/container-registry/

| Operation | Status |
| --- | --- |
| CacheRules.Create | Implemented |
| CacheRules.Delete | Implemented |
| CacheRules.Get | Implemented |
| CacheRules.List | Implemented |
| CacheRules.Update | Implemented |
| ConnectedRegistries.Create | Implemented |
| ConnectedRegistries.Deactivate | Implemented |
| ConnectedRegistries.Delete | Implemented |
| ConnectedRegistries.Get | Implemented |
| ConnectedRegistries.List | Implemented |
| ConnectedRegistries.Update | Implemented |
| CredentialSets.Create | Implemented |
| CredentialSets.Delete | Implemented |
| CredentialSets.Get | Implemented |
| CredentialSets.List | Implemented |
| CredentialSets.Update | Implemented |
| Operations.List | Implemented |
| PrivateEndpointConnections.CreateOrUpdate | Implemented |
| PrivateEndpointConnections.Delete | Implemented |
| PrivateEndpointConnections.Get | Implemented |
| PrivateEndpointConnections.List | Implemented |
| Registries.CheckNameAvailability | Implemented |
| Registries.Create | Implemented |
| Registries.Delete | Implemented |
| Registries.GenerateCredentials | Implemented |
| Registries.Get | Implemented |
| Registries.GetBuildSourceUploadUrl | Implemented |
| Registries.GetPrivateLinkResource | Implemented |
| Registries.ImportImage | Implemented |
| Registries.List | Implemented |
| Registries.ListByResourceGroup | Implemented |
| Registries.ListCredentials | Implemented |
| Registries.ListPolicies | Implemented |
| Registries.ListPrivateLinkResources | Implemented |
| Registries.ListUsages | Implemented |
| Registries.RegenerateCredential | Implemented |
| Registries.ScheduleRun | Implemented |
| Registries.Update | Implemented |
| Registries.UpdatePolicies | Implemented |
| Replications.Create | Implemented |
| Replications.Delete | Implemented |
| Replications.Get | Implemented |
| Replications.List | Implemented |
| Replications.Update | Implemented |
| Runs.Cancel | Not implemented |
| Runs.Get | Not implemented |
| Runs.GetLogSasUrl | Implemented |
| Runs.List | Not implemented |
| Runs.Update | Not implemented |
| ScopeMaps.Create | Implemented |
| ScopeMaps.Delete | Implemented |
| ScopeMaps.Get | Implemented |
| ScopeMaps.List | Implemented |
| ScopeMaps.Update | Implemented |
| Tasks.Create | Not implemented |
| Tasks.Delete | Not implemented |
| Tasks.Get | Not implemented |
| Tasks.GetDetails | Not implemented |
| Tasks.List | Not implemented |
| Tasks.Update | Not implemented |
| Tokens.Create | Implemented |
| Tokens.Delete | Implemented |
| Tokens.Get | Implemented |
| Tokens.List | Implemented |
| Tokens.Update | Implemented |
| Webhooks.Create | Implemented |
| Webhooks.Delete | Implemented |
| Webhooks.Get | Implemented |
| Webhooks.GetCallbackConfig | Implemented |
| Webhooks.List | Implemented |
| Webhooks.ListEvents | Implemented |
| Webhooks.Ping | Implemented |
| Webhooks.Update | Implemented |
