Registry with limited public internet access
Azure Private Link allows you to access Azure PaaS service over a private endpoint in our virtual network. After enabling private endpoint on the Azure Container Registry, you can disable public internet access and allow private link access only. However, if you use Azure Container Tasks to build and push the images or run image purge jobs which need to access the registry, you will immediately start to see access deny. It’s because ACR Tasks run on the “public” Azure machine pools whose outbound requests go through a set of public endpoints. The registry with limited or no public internet access will reject the requests from these public endpoints by default. Here are a couple of solutions.
Solution: Dedicated agent pool
If you want to disable public internet access without any exception, the best option is to use Tasks dedicated agent pool. The dedicated agent pool feature will provision the machines into your virtual network, the Tasks jobs running on the dedicated agent pool will connect to the registry through the designated private endpoint safely.
Solution: Configure public IP network rules
Tasks reserve a set of public IPs in each region (a.k.a. AzureContainerRegistry Service Tag) for outbound requests. You can choose to add the IPs in the firewall allowed list.
Query AzureContainerRegistry Service Tag IPs
Tasks agent pools are running on the same region where the registry is created. Once you confirm the registry home region, you can use it to query the regional Service Tag IPs. The following example shows the az command to query the IPs (both IPv4 and IPv6) in EastUS region.
# Prerequisite
# 1) Install azure-cli
az network list-service-tags --location eastus --query "values[?id == 'AzureContainerRegistry.EastUS'].properties.addressPrefixes[]" -o tsv
- 20.42.66.0/24
- 20.42.67.0/24
- 20.42.74.64/26
- 20.62.128.0/26
- 40.71.10.216/29
- 40.78.226.208/29
- 40.78.231.0/24
- 40.79.154.104/29
- 52.168.112.192/26
- 52.168.114.0/24
- 52.168.115.0/24
- 2603:1030:210:402::90/125
- 2603:1030:210:402::340/122
- 2603:1030:210:402::580/121
- 2603:1030:210:802::90/125
- 2603:1030:210:802::2c0/122
- 2603:1030:210:802::400/121
- 2603:1030:210:c02::90/125
- 2603:1030:210:c02::400/121
Allow Service Tag IPv4 in ACR firewall
ACR firewall rule currently only supports IPv4 CIDR. In the above example, IPv4 CIDR is highlighted. You can add them to the ACR firewall IP rules using Azure Portal or AZ CLI.
# Prerequisite
# 1) Install azure-cli
az acr network-rule add -n myregistry --ip-address "20.42.66.0/24"
az acr network-rule add -n myregistry --ip-address "20.42.67.0/24"
az acr network-rule add -n myregistry --ip-address "20.42.74.64/26"
...
Tasks agent pool IP vs Github and Azure DevOps agent pool IP
Tasks provides several commands (eg az acr build
, az acr run
and az acr task run
) in Azure CLI to allow you to trigger the build or run jobs. You can run the commands locally from your dev machine or in your Github and Azure DevOps pipelines. These commands run on your local machine or the Github and Azure DevOps agent pools machines. However, the build and run jobs run on the Tasks agent pool machines. The IPs of the Github and Azure DevOps agent pool are different from the Tasks agent pool. When you configure the registry firewall rules, you need to make sure you add the IPs of the Tasks agent pool which you can query from the AzureContainerRegistry Service Tag.
Solution: Bypass Network Rule For Tasks
Azure Container Registry also provides a mode to allow Tasks system identity to bypass the registry’s network rule to perform registry operations through public endpoint. The following are two examples. ß
NOTE: ACR Tasks only supports system-assigned identity in bypass mode and you also need to disable the default auth mode on the task.
IMPORTANT: Since ACR Tasks allow customers to run any code, it is customer’s responbility to protect the system-assigned identity token.
Example: Purge images task
# PrerequisiteAdd commentMore actions
# 1) Install azure-cli
registry_name="myregistry"
task_name="mypurgetask"
cmd="acr purge --filter 'hello-world:.*' --untagged --ago 1d --dry-run"
echo "enable network rule bypass policy on registry: $registry_name"
resource_group=$(az acr show -n $registry_name --query "resourceGroup" -o tsv)
az resource update --namespace Microsoft.ContainerRegistry --resource-type registries --name $registry_name --resource-group $resource_group --api-version 2025-05-01-preview --set properties.networkRuleBypassAllowedForTasks=true
registry_login_server=$(az acr show -n $registry_name --query "loginServer" -o tsv)
echo "registry login server: $registry_login_server"
echo "create task with system identity enabled: $task_name"
system_identity_principal=$(az acr task create -r $registry_name -n $task_name --cmd "$cmd" -c /dev/null --assign-identity [system] --auth-mode None --base-image-trigger-enabled false --query "identity.principalId" -o tsv)
echo "system identity principal: $system_identity_principal"
registry_resource_id=$(az acr show -n $registry_name --query "id" -o tsv)
echo "assign AcrPush role to the system ideneity for registry: $registry_resource_id"
az role assignment create --role AcrPush --assignee-object-id $system_identity_principal --assignee-principal-type ServicePrincipal --scope $registry_resource_id
echo "enable system identity login on registry: $registry_login_server"
az acr task credential add -r $registry_name -n $task_name --login-server $registry_login_server --use-identity [system]
az acr task run -r $registry_name -n $task_name
Example: Build with local source
-
If you want to run ad-hoc container image build with bypass mode, you need to first create a placeholder task resource in the registry with the following
acb.yaml
. It is one-time setup.version: v1.1.0 steps: - build: -t $Registry/{{.Values.image}} -f {{.Values.dockerfile}} . - push: - $Registry/{{.Values.image}}
# Prerequisite # 1) Install azure-cli registry_name="myregistry" task_name="mybuildtask" echo "enable network rule bypass policy on registry: $registry_name" resource_group=$(az acr show -n $registry_name --query "resourceGroup" -o tsv) az resource update --namespace Microsoft.ContainerRegistry --resource-type registries --name $registry_name --resource-group $resource_group --api-version 2025-05-01-preview --set properties.networkRuleBypassAllowedForTasks=true echo "create task with system identity enabled: $task_name" system_identity_principal=$(az acr task create -r $registry_name -n $task_name -f acb.yaml -c /dev/null --assign-identity [system] --auth-mode None --base-image-trigger-enabled false --query "identity.principalId" -o tsv) echo "system identity principal: $system_identity_principal" registry_resource_id=$(az acr show -n $registry_name --query "id" -o tsv) echo "assign AcrPush role to the system ideneity for registry: $registry_resource_id" az role assignment create --role AcrPush --assignee-object-id $system_identity_principal --assignee-principal-type ServicePrincipal --scope $registry_resource_id echo "enable system identity login on registry: $registry_login_server" az acr task credential add -r $registry_name -n $task_name --login-server $registry_login_server --use-identity [system]
-
Schedule the task run with the local source to build/push the image to the registry.
registry_name="myregistry" task_name="mybuildtask" az acr task run -r $registry_name -n $task_name --set image=myrepo:mytag --set dockerfile=Dockerfile -c .