For the first time I am trying to deploy the container app.
I have a Azure Container Registry already deployed. I have set the permissions for the Azure Service Connection for ACR pull / push etcetera on subscription level.
First thing I do is building and pushing the image to the registry via Azure Devops pipeline. This works good. I also have the container app environment Second I am using an Arm template for creating the container app.
- task: AzureResourceManagerTemplateDeployment@3
displayName: "Create Container App"
inputs:
deploymentScope: 'Resource Group'
azureResourceManagerConnection: $(serviceConnection)
subscriptionId: '$(SubscriptionID)'
action: 'Create Or Update Resource Group'
resourceGroupName: '$(ResourceGroupName)'
location: 'West Europe'
templateLocation: 'Linked artifact'
csmFile: '$(Pipeline.Workspace)/drop/armtemplates/container_deployment.json'
csmParametersFile: '$(Pipeline.Workspace)/drop/armtemplates/container_parameters.json'
deploymentMode: 'Incremental'
continueOnError: false
The resource part of the template:
"resources": [
{
"type": "Microsoft.App/containerApps",
"apiVersion": "2023-05-01",
"name": "[parameters('containerAppName')]",
"location": "[parameters('location')]",
"properties": {
"managedEnvironmentId": "[resourceId('Microsoft.App/managedEnvironments', parameters('containerAppEnvName'))]",
"configuration": {
"ingress": {
"external": true,
"targetPort": "[parameters('targetPort')]",
"allowInsecure": false,
"traffic": [
{
"latestRevision": true,
"weight": 100
}
]
}
},
"template": {
"revisionSuffix": "firstrevision",
"containers": [
{
"name": "[parameters('containerAppName')]",
"image": "[parameters('containerImage')]",
"resources": {
"cpu": "[json(parameters('cpuCore'))]",
"memory": "[format('{0}Gi', parameters('memorySize'))]"
}
}
],
"scale": {
"minReplicas": "[parameters('minReplicas')]",
"maxReplicas": "[parameters('maxReplicas')]"
}
}
}
}
]
}
Error details: The following field(s) are either invalid or missing. Field 'template.containers.NameContainerApp.image' is invalid with details: 'Invalid value: "containerregistryname.azurecr.io/todolistapp:latest": GET https:?scope=repository%3Atodolistapp%3Apull&service=containerregistryname.azurecr.io: UNAUTHORIZED: authentication required
What needs exactly the required authorization in this case?
In your template, you didn't provide credentials in the Container Apps configuration when you deploy images hosted on private registries.
Solution:
You can deploy images hosted on private registries by providing credentials in the Container Apps configuration.
You can define the registry in the registries array in the properties.configuration section of the container app resource template. The
passwordSecretRef
field identifies the name of the secret in thesecrets
array name where you defined the password.
Steps:
Enable the admin user in the Access keys and you will get the password.
In the pipeline, set a secret variable named secrets
, the value is the password you get in the Access keys.
In your container_deployment.json
, add the secrets
and registries
in properties configuration.
Sample resources part:
"resources": [
{
"type": "Microsoft.App/containerApps",
"apiVersion": "2023-05-01",
"name": "[parameters('containerAppName')]",
"location": "[parameters('location')]",
"properties": {
"managedEnvironmentId": "[resourceId('Microsoft.App/managedEnvironments', parameters('containerAppEnvName'))]",
"configuration": {
"ingress": {
"external": true,
"targetPort": "[parameters('targetPort')]",
"allowInsecure": false,
"traffic": [
{
"latestRevision": true,
"weight": 100
}
]
},
"secrets": [
{
"name": "myregistrypassword",
"value": "[parameters('registry_password')]"
}
],
"registries": [
{
"server": "miao0909.azurecr.io",
"username": "miao0909",
"passwordSecretRef": "myregistrypassword"
}
],
"activeRevisionsMode": "Single"
},
"template": {
"revisionSuffix": "firstrevision",
"containers": [
{
"name": "[parameters('containerAppName')]",
"image": "[parameters('containerImage')]",
"resources": {
"cpu": "[json(parameters('cpuCore'))]",
"memory": "[format('{0}Gi', parameters('memorySize'))]"
}
}
],
"scale": {
"minReplicas": "[parameters('minReplicas')]",
"maxReplicas": "[parameters('maxReplicas')]"
}
}
}
}
]
registry_password
parameter with Parameters: '-registry_password $(secrets)'
in the AzureResourceManagerTemplateDeployment@3
task.- task: AzureResourceManagerTemplateDeployment@3
displayName: 'ARM Template deployment: Resource Group scope'
inputs:
deploymentScope: 'Resource Group'
azureResourceManagerConnection: ''
subscriptionId: ''
action: 'Create Or Update Resource Group'
resourceGroupName: 'Default'
location: ''
templateLocation: 'Linked artifact'
csmFile: '$(Pipeline.Workspace)/drop/armtemplates/container_deployment.json'
csmParametersFile: '$(Pipeline.Workspace)/drop/armtemplates/container_parameters.json'
overrideParameters: '-registry_password $(secrets)'
deploymentMode: 'Incremental'
You can use an Azure managed identity to authenticate with Azure Container Registry instead of using a username and password. For more information, see Managed identities in Azure Container Apps.
To use managed identity with a registry, the identity must be enabled in the app and it must be assigned acrPull role in the registry. To configure the registry, use the managed identity resource ID for a user-assigned identity, or system for the system-assigned identity in the identity property of the registry. Don't configure a username and password when using managed identity.
Steps:
Sample resources part:
"resources": [
{
"identity": {
"userAssignedIdentities": {
"/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/Default/providers/Microsoft.ManagedIdentity/userAssignedIdentities/username": {}
},
"type": "UserAssigned"
},
"type": "Microsoft.App/containerApps",
"apiVersion": "2023-05-01",
"name": "[parameters('containerAppName')]",
"location": "[parameters('location')]",
"properties": {
"managedEnvironmentId": "[resourceId('Microsoft.App/managedEnvironments', parameters('containerAppEnvName'))]",
"configuration": {
"ingress": {
"external": true,
"targetPort": "[parameters('targetPort')]",
"allowInsecure": false,
"traffic": [
{
"latestRevision": true,
"weight": 100
}
]
},
"registries": [
{
"server": "miao0909.azurecr.io",
"identity": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/Default/providers/Microsoft.ManagedIdentity/userAssignedIdentities/username"
}
],
"activeRevisionsMode": "Single"
},
"template": {
"revisionSuffix": "firstrevision",
"containers": [
{
"name": "[parameters('containerAppName')]",
"image": "[parameters('containerImage')]",
"resources": {
"cpu": "[json(parameters('cpuCore'))]",
"memory": "[format('{0}Gi', parameters('memorySize'))]"
}
}
],
"scale": {
"minReplicas": "[parameters('minReplicas')]",
"maxReplicas": "[parameters('maxReplicas')]"
}
}
}
}
]