Azure Container Apps image pull with managed identity

You can pull images from private repositories in Azure Container Registry using managed identities for authentication to avoid the use of administrative credentials.

You can use a user-assigned or system-assigned managed identity to authenticate with Azure Container Registry.

  • With a user-assigned managed identity, you create and manage the identity outside of Azure Container Apps. It can be assigned to multiple Azure resources, including Azure Container Apps.
  • With a system-assigned managed identity, the identity is created and managed by Azure Container Apps. It is tied to your container app and is deleted when your app is deleted.
  • When possible, you should use a user-assigned managed identity to pull images.

Container Apps checks for a new version of the image whenever a container is started. In Docker or Kubernetes terminology, Container Apps sets each container's image pull policy to always.

This article describes how to use the Azure portal to configure your container app to use user-assigned and system-assigned managed identities to pull images from private Azure Container Registry repositories.

User-assigned managed identity

The following steps describe the process to configure your container app to use a user-assigned managed identity to pull images from private Azure Container Registry repositories.

  1. Create a container app with a public image.
  2. Add the user-assigned managed identity to the container app.
  3. Create a container app revision with a private image and the user-assigned managed identity.

Prerequisites

  • An Azure account with an active subscription.

  • A private Azure Container Registry containing an image you want to pull.

  • Your Azure Container Registry must allow ARM audience tokens for authentication in order to use managed identity to pull images. Use the following command to check if ARM tokens are allowed to access your ACR:

    az acr config authentication-as-arm show -r <REGISTRY>
    

    If ARM tokens are disallowed, you can allow them with the following command:

    az acr config authentication-as-arm update -r <REGISTRY> --status enabled
    
  • Create a user-assigned managed identity. For more information, see Create a user-assigned managed identity.

Create a container app

Use the following steps to create a container app with the default quickstart image.

  1. Navigate to the portal Home page.

  2. Search for Container Apps in the top search bar.

  3. Select Container Apps in the search results.

  4. Select the Create button.

  5. In the Basics tab, do the following actions.

    Setting Action
    Subscription Select your Azure subscription.
    Resource group Select an existing resource group or create a new one.
    Container app name Enter a container app name.
    Location Select a location.
    Create Container App Environment Create a new or select an existing environment.
  6. Select the Review + Create button at the bottom of the Create Container App page.

  7. Select the Create button at the bottom of the Create Container App window.

Allow a few minutes for the container app deployment to finish. When deployment is complete, select Go to resource.

Add the user-assigned managed identity

  1. Select Identity from the left menu.
  2. Select the User assigned tab.
  3. Select the Add user assigned managed identity button.
  4. Select your subscription.
  5. Select the identity you created.
  6. Select Add.

Create a container app revision

Create a container app revision with a private image and the system-assigned managed identity.

  1. Select Revision Management from the left menu.

  2. Select Create new revision.

  3. Select the container image from the Container Image table.

  4. Enter the information in the Edit a container dialog.

    Field Action
    Name Enter a name for the container.
    Image source Select Azure Container Registry.
    Authentication Select Managed Identity.
    Identity Select the identity you created from the drop-down menu.
    Registry Select the registry you want to use from the drop-down menu.
    Image Enter the name of the image you want to use.
    Image Tag Enter the name and tag of the image you want to pull.

    Screen shot of the Edit a container dialog entering user assigned managed identity.

    Note

    If the administrative credentials are not enabled on your Azure Container Registry registry, you will see a warning message displayed and you will need to enter the image name and tag information manually.

  5. Select Save.

  6. Select Create from the Create and deploy new revision page.

A new revision will be created and deployed. The portal will automatically attempt to add the acrpull role to the user-assigned managed identity. If the role isn't added, you can add it manually.

You can verify that the role was added by checking the identity from the Identity pane of the container app page.

  1. Select Identity from the left menu.
  2. Select the User assigned tab.
  3. Select the user-assigned managed identity.
  4. Select Azure role assignments from the menu on the managed identity resource page.
  5. Verify that the acrpull role is assigned to the user-assigned managed identity.

Create a container app with a private image

If you don't want to start by creating a container app with a public image, you can also do the following.

  1. Create a user-assigned managed identity.
  2. Add the acrpull role to the user-assigned managed identity.
  3. Create a container app with a private image and the user-assigned managed identity.

This method is typical in Infrastructure as Code (IaC) scenarios.

Clean up resources

If you're not going to continue to use this application, you can delete the Azure Container Apps instance and all the associated services by removing the resource group.

Warning

Deleting the resource group will delete all the resources in the group. If you have other resources in the group, they will also be deleted. If you want to keep the resources, you can delete the container app instance and the container app environment.

  1. Select your resource group from the Overview section.
  2. Select the Delete resource group button at the top of the resource group Overview.
  3. Enter the resource group name in the confirmation dialog.
  4. Select Delete. The process to delete the resource group may take a few minutes to complete.

System-assigned managed identity

The method for configuring a system-assigned managed identity in the Azure portal is the same as configuring a user-assigned managed identity. The only difference is that you don't need to create a user-assigned managed identity. Instead, the system-assigned managed identity is created when you create the container app.

The method to configure a system-assigned managed identity in the Azure portal is:

  1. Create a container app with a public image.
  2. Create a container app revision with a private image and the system-assigned managed identity.

Prerequisites

Create a container app

Follow these steps to create a container app with the default quickstart image.

  1. Navigate to the portal Home page.

  2. Search for Container Apps in the top search bar.

  3. Select Container Apps in the search results.

  4. Select the Create button.

  5. In the Basics tab, do the following actions.

    Setting Action
    Subscription Select your Azure subscription.
    Resource group Select an existing resource group or create a new one.
    Container app name Enter a container app name.
    Location Select a location.
    Create Container App Environment Create a new or select an existing environment.
  6. Select the Review + Create button at the bottom of the Create Container App page.

  7. Select the Create button at the bottom of the Create Container App page.

Allow a few minutes for the container app deployment to finish. When deployment is complete, select Go to resource.

Edit and deploy a revision

Edit the container to use the image from your private Azure Container Registry, and configure the authentication to use system-assigned identity.

  1. The Containers from the side menu on the left.

  2. Select Edit and deploy.

  3. Select the simple-hello-world-container container from the list.

    Setting Action
    Name Enter the container app name.
    Image source Select Azure Container Registry.
    Authentication Select Managed identity.
    Identity Select System assigned.
    Registry Enter the Registry name.
    Image Enter the image name.
    Image tag Enter the tag.

    Screen shot Edit a container with system-assigned managed identity.

    Note

    If the administrative credentials are not enabled on your Azure Container Registry registry, you will see a warning message displayed and you will need to enter the image name and tag information manually.

  4. Select Save at the bottom of the page.

  5. Select Create at the bottom of the Create and deploy new revision page

  6. After a few minutes, select Refresh on the Revision management page to see the new revision.

A new revision will be created and deployed. The portal will automatically attempt to add the acrpull role to the system-assigned managed identity. If the role isn't added, you can add it manually.

You can verify that the role was added by checking the identity in the Identity pane of the container app page.

  1. Select Identity from the left menu.
  2. Select the System assigned tab.
  3. Select Azure role assignments.
  4. Verify that the acrpull role is assigned to the system-assigned managed identity.

Clean up resources

If you're not going to continue to use this application, you can delete the Azure Container Apps instance and all the associated services by removing the resource group.

Warning

Deleting the resource group will delete all the resources in the group. If you have other resources in the group, they will also be deleted. If you want to keep the resources, you can delete the container app instance and the container app environment.

  1. Select your resource group from the Overview section.
  2. Select the Delete resource group button at the top of the resource group Overview.
  3. Enter the resource group name in the confirmation dialog.
  4. Select Delete. The process to delete the resource group may take a few minutes to complete.

This article describes how to configure your container app to use managed identities to pull images from a private Azure Container Registry repository using Azure CLI and Azure PowerShell.

Prerequisites

Prerequisite Description
Azure account An Azure account with an active subscription. If you don't have one, you can Create a trial subscription.
Azure CLI If using Azure CLI, install the Azure CLI on your local machine.
Azure PowerShell If using PowerShell, install the Azure PowerShell on your local machine. Ensure that the latest version of the Az.App module is installed by running the command Install-Module -Name Az.App.
Azure Container Registry A private Azure Container Registry containing an image you want to pull. Quickstart: Create a private container registry using the Azure CLI or Quickstart: Create a private container registry using Azure PowerShell

Setup

To sign in to Azure from the CLI, run the following command and follow the prompts to complete the authentication process.

az cloud set -n AzureChinaCloud
az login
# az cloud set -n AzureCloud   //means return to Public Azure.

To ensure you're running the latest version of the CLI, run the upgrade command.

az upgrade

Next, install or update the Azure Container Apps extension for the CLI.

If you receive errors about missing parameters when you run az containerapp commands in Azure CLI or cmdlets from the Az.App module in Azure PowerShell, be sure you have the latest version of the Azure Container Apps extension installed.

az extension add --name containerapp --upgrade

Note

Starting in May 2024, Azure CLI extensions no longer enable preview features by default. To access Container Apps preview features, install the Container Apps extension with --allow-preview true.

az extension add --name containerapp --upgrade --allow-preview true

Now that the current extension or module is installed, register the Microsoft.App and Microsoft.OperationalInsights namespaces.

Note

Azure Container Apps resources have migrated from the Microsoft.Web namespace to the Microsoft.App namespace. Refer to Namespace migration from Azure.Web to Microsoft.App in March 2022 for more details.

az provider register --namespace Microsoft.App
az provider register --namespace Microsoft.OperationalInsights

Next, set the following environment variables. Replace the placeholders surrounded by <> with your values.

RESOURCE_GROUP="<YOUR_RESOURCE_GROUP_NAME>"
LOCATION="<YOUR_LOCATION>"
CONTAINERAPPS_ENVIRONMENT="<YOUR_ENVIRONMENT_NAME>"
REGISTRY_NAME="<YOUR_REGISTRY_NAME>"
CONTAINERAPP_NAME="<YOUR_CONTAINERAPP_NAME>"
IMAGE_NAME="<YOUR_IMAGE_NAME>"

If you already have a resource group, skip this step. Otherwise, create a resource group.

az group create \
  --name $RESOURCE_GROUP \
  --location $LOCATION

Create a container app environment

If the environment doesn't exist, run the following command:

To create the environment, run the following command:

az containerapp env create \
  --name $CONTAINERAPPS_ENVIRONMENT \
  --resource-group $RESOURCE_GROUP \
  --location $LOCATION

Continue to the next section to configure user-assigned managed identity or skip to the System-assigned managed identity section.

User-assigned managed identity

Follow this procedure to configure user-assigned managed identity:

  1. Create a user-assigned managed identity.
  2. If you're using PowerShell, assign a acrpull role for your registry to the managed identity. The Azure CLI automatically makes this assignment.
  3. Create a container app with the image from the private registry that is authenticated with the user-assigned managed identity.

Create a user-assigned managed identity

Create a user-assigned managed identity. Before you run the following command, replace the <PLACEHOLDERS> with the name of your managed identity.

IDENTITY="<YOUR_IDENTITY_NAME>"
az identity create \
  --name $IDENTITY \
  --resource-group $RESOURCE_GROUP

Get identity's resource ID.

IDENTITY_ID=`az identity show \
  --name $IDENTITY \
  --resource-group $RESOURCE_GROUP \
  --query id`

Create a container app

Create your container app with your image from the private registry authenticated with the identity.

Copy the identity's resource ID to paste into the <IDENTITY_ID> placeholders in the command below. If your image tag isn't latest, replace 'latest' with your tag.

echo $IDENTITY_ID
az containerapp create \
  --name $CONTAINERAPP_NAME \
  --resource-group $RESOURCE_GROUP \
  --environment $CONTAINERAPPS_ENVIRONMENT \
  --user-assigned <IDENTITY_ID> \
  --registry-identity <IDENTITY_ID> \
  --registry-server "$REGISTRY_NAME.azurecr.cn" \
  --image "$REGISTRY_NAME.azurecr.cn/$IMAGE_NAME:latest"

Clean up

Caution

The following command deletes the specified resource group and all resources contained within it. If resources outside the scope of this quickstart exist in the specified resource group, they will also be deleted.

az group delete --name $RESOURCE_GROUP

System-assigned managed identity

To configure a system-assigned identity, you'll need to:

  1. Create a container app with a public image.
  2. Assign a system-assigned managed identity to the container app.
  3. Update the container app with the private image.

Create a container app

Create a container with a public image.

az containerapp create \
  --name $CONTAINERAPP_NAME \
  --resource-group $RESOURCE_GROUP \
  --environment $CONTAINERAPPS_ENVIRONMENT \
  --image mcr.microsoft.com/k8se/quickstart:latest \
  --target-port 80 \
  --ingress external

Update the container app

Update the container app with the image from your private container registry and add a system-assigned identity to authenticate the Azure Container Registry pull. You can also include other settings necessary for your container app, such as ingress, scale and Dapr settings.

Set the registry server and turn on system-assigned managed identity in the container app.

az containerapp registry set \
  --name $CONTAINERAPP_NAME \
  --resource-group $RESOURCE_GROUP \
  --identity system \
  --server "$REGISTRY_NAME.azurecr.cn"
az containerapp update \
  --name $CONTAINERAPP_NAME \
  --resource-group $RESOURCE_GROUP \
  --image "$REGISTRY_NAME.azurecr.cn/$IMAGE_NAME:latest"

Clean up

Caution

The following command deletes the specified resource group and all resources contained within it. If resources outside the scope of this quickstart exist in the specified resource group, they will also be deleted.

az group delete --name $RESOURCE_GROUP

This article describes how to use a Bicep template to configure your container app to use user-assigned managed identities to pull images from private Azure Container Registry repositories.

Prerequisites

Setup

To sign in to Azure from the CLI, run the following command and follow the prompts to complete the authentication process.

az cloud set -n AzureChinaCloud
az login
# az cloud set -n AzureCloud   //means return to Public Azure.

To ensure you're running the latest version of the CLI, run the upgrade command.

az upgrade

Next, install or update the Azure Container Apps extension for the CLI.

If you receive errors about missing parameters when you run az containerapp commands in Azure CLI or cmdlets from the Az.App module in Azure PowerShell, be sure you have the latest version of the Azure Container Apps extension installed.

az extension add --name containerapp --upgrade

Note

Starting in May 2024, Azure CLI extensions no longer enable preview features by default. To access Container Apps preview features, install the Container Apps extension with --allow-preview true.

az extension add --name containerapp --upgrade --allow-preview true

Now that the current extension or module is installed, register the Microsoft.App and Microsoft.OperationalInsights namespaces.

Note

Azure Container Apps resources have migrated from the Microsoft.Web namespace to the Microsoft.App namespace. Refer to Namespace migration from Azure.Web to Microsoft.App in March 2022 for more details.

az provider register --namespace Microsoft.App
az provider register --namespace Microsoft.OperationalInsights

Install Bicep

If you don't have Bicep installed, you can install it as follows.

az bicep install

If you do have Bicep installed, make sure you have the latest version.

az bicep upgrade

For more information, see Installing Bicep.

Set environment variables

Next, set the following environment variables. Replace placeholders surrounded by <> with your values.

RESOURCE_GROUP="<RESOURCE_GROUP_NAME>"
LOCATION="<LOCATION>"
REGISTRY_NAME="<REGISTRY_NAME>"
IMAGE_NAME="<IMAGE_NAME>"
IMAGE_TAG="<IMAGE_TAG>"
BICEP_TEMPLATE="<BICEP_TEMPLATE>"
CONTAINERAPPS_ENVIRONMENT="<ENVIRONMENT_NAME>"
CONTAINER_NAME="<CONTAINER_NAME>"
CONTAINERAPP_NAME="<CONTAINERAPP_NAME>"
USER_ASSIGNED_IDENTITY_NAME="<USER_ASSIGNED_IDENTITY_NAME>"
LOG_ANALYTICS_WORKSPACE_NAME="<LOG_ANALYTICS_WORKSPACE_NAME>"
APP_INSIGHTS_NAME="<APP_INSIGHTS_NAME>"
ACR_PULL_DEFINITION_ID="7f951dda-4ed3-4680-a7ca-43fe172d538d"

The AcrPull role grants your user-assigned managed identity permission to pull the image from the registry.

Bicep template

Copy the following Bicep template and save it as a file with the extension .bicep.

param environmentName string 
param logAnalyticsWorkspaceName string
param appInsightsName string
param containerAppName string 
param azureContainerRegistry string
param azureContainerRegistryImage string 
param azureContainerRegistryImageTag string
param acrPullDefinitionId string
param userAssignedIdentityName string
param location string = resourceGroup().location

resource identity 'Microsoft.ManagedIdentity/userAssignedIdentities@2022-01-31-preview' = {
  name: userAssignedIdentityName
  location: location 
}

resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  name: guid(resourceGroup().id, azureContainerRegistry, 'AcrPullTestUserAssigned')
  properties: {
    principalId: identity.properties.principalId  
    principalType: 'ServicePrincipal'
    // acrPullDefinitionId has a value of 7f951dda-4ed3-4680-a7ca-43fe172d538d
    roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', acrPullDefinitionId)
  }
}

resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' = {
  name: logAnalyticsWorkspaceName
  location: location
  properties: any({
    retentionInDays: 30
    features: {
      searchVersion: 1
    }
    sku: {
      name: 'PerGB2018'
    }
  })
}

resource appInsights 'Microsoft.Insights/components@2020-02-02' = {
  name: appInsightsName
  location: location
  kind: 'web'
  properties: {
    Application_Type: 'web'
    WorkspaceResourceId: logAnalyticsWorkspace.id
  }
}

resource appEnvironment 'Microsoft.App/managedEnvironments@2022-06-01-preview' = {
  name: environmentName
  location: location
  properties: {
    daprAIInstrumentationKey: appInsights.properties.InstrumentationKey
    appLogsConfiguration: {
      destination: 'log-analytics'
      logAnalyticsConfiguration: {
        customerId: logAnalyticsWorkspace.properties.customerId
        sharedKey: logAnalyticsWorkspace.listKeys().primarySharedKey
      }
    }
  }
}

resource containerApp 'Microsoft.App/containerApps@2022-06-01-preview' = {
  name: containerAppName
  location: location
  identity: {
    type: 'UserAssigned'
    userAssignedIdentities: {
      '${identity.id}': {}
    }
  }
  properties: {
    environmentId: appEnvironment.id
    configuration: {
      ingress: {
        targetPort: 8080
        external: true
      }
      registries: [
        {
          server: '${azureContainerRegistry}.azurecr.cn'
          identity: identity.id
        }
      ]
    }
    template: {
      containers: [
        {
          image: '${azureContainerRegistry}.azurecr.cn/${azureContainerRegistryImage}:${azureContainerRegistryImageTag}'
          name: '${azureContainerName}'
          resources: {
            cpu: 1
            memory: '2Gi'
          }
        }
      ]
      scale: {
        minReplicas: 1
        maxReplicas: 1
      }
    }
  }
}

output location string = location
output environmentId string = appEnvironment.id

Deploy the container app

Deploy your container app with the following command.

az deployment group create \
  --resource-group "$RESOURCE_GROUP" \
  --template-file "$BICEP_TEMPLATE" \
  --parameters environmentName="$CONTAINERAPPS_ENVIRONMENT" \
  logAnalyticsWorkspaceName="$LOG_ANALYTICS_WORKSPACE_NAME" \
  appInsightsName="$APP_INSIGHTS_NAME" \
  containerAppName="$CONTAINERAPP_NAME" \
  azureContainerRegistry="$REGISTRY_NAME" \
  azureContainerRegistryImage="$IMAGE_NAME" \
  azureContainerRegistryImageTag="$IMAGE_TAG" \
  azureContainerName="$CONTAINER_NAME" \
  acrPullDefinitionId="$ACR_PULL_DEFINITION_ID" \
  userAssignedIdentityName="$USER_ASSIGNED_IDENTITY_NAME" \
  location="$LOCATION"

This command deploys the following.

  • An Azure resource group.
  • A Container Apps environment.
  • A Log Analytics workspace associated with the Container Apps environment.
  • An Application Insights resource for distributed tracing.
  • A user-assigned managed identity.
  • A container to store the image.
  • A container app based on the image.

If you receive the error Failed to parse '<YOUR_BICEP_FILE_NAME>', please check whether it is a valid JSON format, make sure your Bicep template file has the extension .bicep.

Additional resources

For more information, see the following.

Next steps