Reputation: 62712
The Container Setting on the App Service it self look solid:
But the log pane shows errors:
2020-02-11 06:31:40.621 ERROR - Image pull failed: Verify docker image configuration and credentials (if using private repository)
2020-02-11 06:31:41.240 INFO - Stoping site app505-dfpg-qa2-web-eastus2-gateway-apsvc because it failed during startup.
2020-02-11 06:36:05.546 INFO - Starting container for site
2020-02-11 06:36:05.551 INFO - docker run -d -p 9621:8081 --name app505-dfpg-qa2-web-eastus2-gateway-apsvc_0_a9c8277e_msiProxy -e WEBSITE_SITE_NAME=app505-dfpg-qa2-web-eastus2-gateway-apsvc -e WEBSITE_AUTH_ENABLED=False -e WEBSITE_ROLE_INSTANCE_ID=0 -e WEBSITE_HOSTNAME=app505-dfpg-qa2-web-eastus2-gateway-apsvc.azurewebsites.net -e WEBSITE_INSTANCE_ID=7d18d5957d129d3dc3a25d7a2c85147ef57f1a6b93910c50eb850417ab59dc56 appsvc/msitokenservice:1904260237
2020-02-11 06:36:05.552 INFO - Logging is not enabled for this container.
Please use https://aka.ms/linux-diagnostics to enable logging to see container logs here.
2020-02-11 06:36:17.766 INFO - Pulling image: a...cr/gateway:1.0.20042.2
2020-02-11 06:36:17.922 ERROR - DockerApiException: Docker API responded with status code=NotFound, response={"message":"pull access denied for a...cr/gateway, repository does not exist or may require 'docker login': denied: requested access to the resource is denied"}
2020-02-11 06:36:17.923 ERROR - Pulling docker image a...cr/gateway:1.0.20042.2 failed:
2020-02-11 06:36:17.923 INFO - Pulling image from Docker hub: a...cr/gateway:1.0.20042.2
2020-02-11 06:36:18.092 ERROR - DockerApiException: Docker API responded with status code=NotFound, response={"message":"pull access denied for a...cr/gateway, repository does not exist or may require 'docker login': denied: requested access to the resource is denied"}
2020-02-11 06:36:18.094 ERROR - Image pull failed: Verify docker image configuration and credentials (if using private repository)
2020-02-11 06:36:19.062 INFO - Stoping site app505-dfpg-qa2-web-eastus2-gateway-apsvc because it failed during startup.
The Service Principal used to deploy the App Service has AcrPush access to the parent resource group of the container registry:
The setting are present:
I did az login
with that service principal and then tried az acr login
to the registry. It works fine. So what am I missing here?
EDIT 1
I know the credentials are correct, because I tested them like this:
Where I just copied the values from the app service configuration and pasted on the console. docker has no problem logging in.
It must be something else.
EDIT 2
However, I also get this:
C:\Dayforce\fintech [shelve/terraform ≡]> docker pull a...r/gateway
Using default tag: latest
Error response from daemon: pull access denied for a...r/gateway, repository does not exist or may require 'docker login': denied: requested access to the resource is denied
So, I can login, but not pull. Very strange, because the account is configured to have AcrPush
access to the container, which includes AcrPull
:
EDIT 3
I was able to pull successfully when using the FQDN for the registry:
I updated the pipeline, but I still get the same errors:
2020-02-11 16:03:50.227 ERROR - Pulling docker image a...r.azurecr.io/gateway:1.0.20042.2 failed:
2020-02-11 16:03:50.228 INFO - Pulling image from Docker hub: a...r.azurecr.io/gateway:1.0.20042.2
2020-02-11 16:03:50.266 ERROR - DockerApiException: Docker API responded with status code=InternalServerError, response={"message":"Get https://a...r.azurecr.io/v2/gateway/manifests/1.0.20042.2: unauthorized: authentication required"}
2020-02-11 16:03:50.269 ERROR - Image pull failed: Verify docker image configuration and credentials (if using private repository)
2020-02-11 16:03:50.853 INFO - Stoping site app505-dfpg-qa2-web-eastus2-gateway-apsvc because it failed during startup.
EDIT 4
The only way that I found working was to enable the Admin User on the ACR and pass its credentials in the DOCKER_... variables instead of credentials of the Service Principal.
This is frustrating, I know the Service Principal can login and pull when ran locally, it is a mystery why it does not work for docker running on an App Service Host. We have another team here which faced the same issue and they have not found any solution, but enable the Admin User.
EDIT 5
The entire process runs as part of the Azure DevOps on-prem release pipeline using a dedicated Service Principal. Let me call it Pod Deploy Service Principal or just SP for short.
Let DOCKER_xyz
denote the three app settings controlling the docker running on the App Service host:
DOCKER_REGISTRY_SERVER_URL
DOCKER_REGISTRY_SERVER_USERNAME
DOCKER_REGISTRY_SERVER_PASSWORD
I think we need to distinguish two parts here:
DOCKER_xyz
app settings. I think that the DOCKER_xyz
app settings are not for that, but for the second part.DOCKER_xyz
app settings.My problem is that part (1) works great, but part (2) does not even if DOCKER_xyz
app settings specify the credentials of the SP from part (1). The only way I could make it work if I point DOCKER_xyz
at the Admin User of the ACR.
But that why on Earth the DOCKER_xyz
app settings cannot point to the pipeline SP, which was good enough for the part (1)?
EDIT 6
The current state of affairs is this. Azure App Service is unable to communicate with an ACR except using ACR admin user and password. So, even if the docker runtime running on the App Service host machine may know how to login using any service principal, the App Service would not use any identity or Service Principal to read metadata from the ACR - only admin user and password. The relevant references are:
On a personal note I find it amazing that Microsoft recommends not to use ACR admin user, yet a very core piece of their offering, namely Azure App Service, depends on it being enable. Makes me wonder whether different teams in Microsoft are aware of what others are doing or not doing...
Upvotes: 49
Views: 66170
Reputation: 19901
When trying to deploy using a user-assigned identity, you have to realize that there are two different identities here and we need to specify both identities to get this to work as the image below shows:
To specify the ACR identity using Azure CLI, you can either use
$property = "properties.siteConfig.AcrUserManagedIdentityID=${ClientID}"
$tmp = az resource update `
--ids $appServiceID `
--set $property `
--output json | ConvertFrom-Json
or setting it using JSON
$data="{\""acrUserManagedIdentityID\"": \""${clientId}\""}"
$tmp = az webapp config set `
--resource-group $rgname `
--name $AppServiceName_container_linux `
--generic-configurations $data `
--output json | ConvertFrom-Json
To ensure that it is setup correctly, we can query the App Service configuration using:
$settings = az webapp config show `
--resource-group $rgname `
--name $AppServiceName_container_linux `
--output json | ConvertFrom-Json
Write-Host "`nThese two settings must be set for successful ACR pull:"
Write-Host "acrUseManagedIdentityCreds='$($settings.acrUseManagedIdentityCreds)'"
Write-Host "acrUserManagedIdentityID='$($settings.acrUserManagedIdentityId)'"
The acrUseManagedIdentityCreds should be set to true and the acrUserManagedIdentityID should contain the GUID for your managed identity.
The above assumes that you have assigned the AcrPull role to the identity.
$role = az role assignment create `
--assignee $principalId `
--role "AcrPull" `
--scope $acrid `
--output json `
| ConvertFrom-Json
I blogged about the process in more detail here https://nestenius.se/2024/08/27/deploy-a-container-to-azure-app-services-using-azure-cli-and-user-assigned-managed-identity/
Upvotes: 0
Reputation: 11
Here is the solution without using ACR admin credentials, SCM, and FTP, which will soon be deprecated.
DOCKER_REGISTRY_SERVER_USERNAME
to the Application (Client) ID of "app-acr-push".DOCKER_REGISTRY_SERVER_PASSWORD
to the previously saved credentials from "app-acr-push".Now your Web App is connected to the Azure Container Registry.
Try restarting the Web App to see the new deployment attempt.
Upvotes: 0
Reputation: 76
Using only application_stack
and add ignore_changes
worked for me.
resource "azurerm_linux_web_app" "app" {
name = "app-${var.PRODUCT}"
site_config {
application_stack {
docker_image_name = "my-image:e3920202"
docker_registry_url = "https://${data.azurerm_container_registry.acr.login_server}"
docker_registry_username = data.azurerm_container_registry.acr.admin_username
docker_registry_password = data.azurerm_container_registry.acr.admin_password
}
lifecycle {
ignore_changes = [
app_settings["DOCKER_CUSTOM_IMAGE_NAME"],
site_config[0].application_stack[0].docker_image_name
]
}
}
reference: https://github.com/hashicorp/terraform-provider-azurerm/issues/16585#issuecomment-1675045540
Upvotes: 0
Reputation: 501
I had same issue, but in my case I had different tag name in my Build pipeline and Release Pipeline.
Upvotes: 0
Reputation: 28800
I experienced this same issue when trying to deploy an Docker application to Azure Web Apps for containers.
When I deployed the application I will get the error below when I checked the App Services > My App Service > Deployment Center > Container Logs:
DockerApiException: Docker API responded with status code=NotFound, response={"message":"pull access denied for a..my-repo/image, repository does not exist or may require 'docker login': denied: requested access to the resource is denied"}.
Here's how I solved it:
The issue was that I was not specifying the full path to the image. I was supposed to include my-registry-url
in the docker image-name
. That is instead of just image-name
I was supposed to use my-registry-url/image-name
, since I am trying to pull from a private repository.
So say these are variables:
promiseapp
promisecicdregistry.azurecr.io
dockerprojects
dockerlinuxprojects
promiseapptest
test-user
12345678
CLI:
My command will be:
az webapp create --resource-group dockerprojects --plan dockerlinuxprojects --name promiseapptest --deployment-container-image-name promisecicdregistry.azurecr.io/promiseapp
az webapp config container set --resource-group dockerprojects --name promiseapptest --docker-custom-image-name promisecicdregistry.azurecr.io/promiseapp --docker-registry-server-url https://promisecicdregistry.azurecr.io --docker-registry-server-user test-user --docker-registry-server-password 12345678
Azure Portal:
To do this on the Azure Portal, simply go to Azure App Services, select the App Service, go to Deployment Center, click on Settings and set up the Deployment pipeline.
Upvotes: 2
Reputation: 2127
In my case, I fixed the error by using the fully qualified Azure Container Registery name like this:
xwezi.azurecr.io
The previous value was
xwezi
When I deploy manually to App Services, I wouldn't get that error. But, when I used Azure App Service deploy task to deploy the container to the App Service, the service won't work correctly. And, the log stream will show the above errors.
Unfortunately, the error messages weren't helpful for me to find this out. But I hope this will save your time :)
Upvotes: 0
Reputation: 51
Found the answer by setting "acrUseManagedIdentityCreds" to True. The second command in this comment: https://stackoverflow.com/a/69120462/17430834
Edit 1: Adding the command
Here is the command that you will need to run to make this change.
az resource update --ids /subscriptions/<subscription-id>/resourceGroups/myResourceGroup/providers/Microsoft.Web/sites/<app-name>/config/web --set properties.acrUseManagedIdentityCreds=True
Upvotes: 5
Reputation: 10313
Just to add to mark's amazing job of working it all through and for the fast readers: for everything to work, one of course also has to enable the admin user (who by default is disabled). For example by issuing:
az acr update -n <your-azureregistry-name> --admin-enabled true
on the console.
Upvotes: 2
Reputation: 846
I was trying to do the same from Azure DevOps pipelines and got the same problem. I didn't find out how to make it work using the ACR name, but it works if you use your_acr_name.azurecr.io instead. If you go to the Access Keys page of your ACR you will find two values Registry name: MyCoolRegistry (doesn't work if you use this one) Login server: mycoolregistry.azurecr.io The login server is working - just put it as the containerRegistry in your Pipeline without creating a service connection.
Just in case someone is struggling with that one.
Upvotes: 2
Reputation: 551
App service started pulling after doing these steps for me. :D
Good luck :)
Upvotes: 37
Reputation: 2178
After a lot of research I figured out a way to resolve this without enabling Admin user
DOCKER_REGISTRY_SERVER_PASSWORD with Client Secret of app registration which was saved in the first step DOCKER_REGISTRY_SERVER_USERNAME with client Id of App registration
This should solve the Docker Api exception.
It's baffling that this is not mentioned in any Azure Container Registry documentation. Although I think it is mentioned somewhere in AAD documentation indirectly 😐.
Upvotes: 9
Reputation: 31384
From the message I got of the talk, let me solve your puzzle about the error.
I guess you deploy the image in ACR to the Web App through the Azure portal. When you use the Azure portal to deploy the Web App from the ACR, it only lets you select the ACR and image and tag, but do not let you set the credential. In this way, Azure will set it itself with the admin user and password if you enable the admin user. If you do not enable it, the error you got happens.
And if you want to use the service principal, I recommend you use the other tools, such as Azure CLI. Then you can set the docker registry credential yourself with the command az webapp config container set
.
Here is the example and it works fine on my side:
With the Azure CLI, you can follow the steps here.
Update:
Here are the screenshots of the test on my side:
Upvotes: 5