Publish docker images to Azure Container Registry with dotnet publish
In the previous article we explored how we can generate docker images of .NET applications and push them to the local Docker Desktop daemon.
Let’s now review how we can push a Docker image to a remote registry. We’ll be using Azure Container Registry as our destination, although the process is similar for all Docker Registries.
Create an Azure Container Registry
Login to your Azure account, and create a new Azure Container Registry. We are going to need the name and the Login server.
dotnet publish with the remote registry
Now we need to tell
dotnet publish that we want to use a remote registry. We are already familiar with
dotnet publish configuration via
.csproj file, so we are going to add a new
<ContainerRegistry> element, so the full
.csproj file looks like this:
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>net7.0</TargetFramework> <Nullable>enable</Nullable> <ImplicitUsings>enable</ImplicitUsings> <ContainerImageName>hello-world-dotnet-publish</ContainerImageName> <ContainerImageTag>1.0.0</ContainerImageTag> <ContainerRegistry>dotnetpublishdemo.azurecr.io</ContainerRegistry> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.NET.Build.Containers" Version="7.0.306" /> </ItemGroup> </Project>
At this point,
dotnet publish will try to push our image to the specified container registry. Do not forget to change
dotnetpublishdemo.azurecr.io to your login server.
If you run it now you will notice that we are getting an error:
error CONTAINER1013: Failed to push to the output registry: Microsoft.NET.Build.Containers.Credentials.CredentialRetrievalException: CONTAINER1008: Failed retrieving credentials for "dotnetpublishdemo.azurecr.io"
Of course, we need to authenticate before we can push or pull docker images to Azure Container Registry. To do this we need to create a service principle and execute
docker login command.
Create a new service principal
There are a few ways we can authenticate Azure CR. We are going to use a service principal authentication since it will also work in a “headless” CI build we will use in future.
Let’s create a new service principal for our Container Registry by executing these commands in Azure Cloud Shell (change
ACR_NAME to your Azure Container Registry name and
SERVICE_PRINCIPAL_NAME your preferred name):
ACR_NAME=DotnetPublishDemo SERVICE_PRINCIPAL_NAME=MyDotnetPublishServicePrincipal ACR_REGISTRY_ID=$(az acr show --name $ACR_NAME --query "id" --output tsv) PASSWORD=$(az ad sp create-for-rbac --name $SERVICE_PRINCIPAL_NAME --scopes $ACR_REGISTRY_ID --role acrpush --query "password" --output tsv) USER_NAME=$(az ad sp list --display-name $SERVICE_PRINCIPAL_NAME --query ".appId" --output tsv) echo "Service principal ID: $USER_NAME" echo "Service principal password: $PASSWORD"
We are going to need your principal id and password, so save it somewhere temporarily. Your service principal password is sensitive information, treat it accordingly.
docker login replacing
myregistry.azurecr.io with your Login server,
$SP_APP_ID with your principal id and
$SP_PASSWD with its password:
docker login myregistry.azurecr.io --username $SP_APP_ID --password $SP_PASSWD
And after pressing enter, you should see
Since we are successfully authenticated, we now can execute our
dotnet publish --os linux --arch x64 -p:PublishProfile=DefaultContainer -c Release command, this time seeing
Pushed container 'hello-world-dotnet-publish:1.0.0' to registry 'dotnetpublishdemo.azurecr.io'
And we can also check it in Azure Portal, navigate to Services > Repositories of Container Registry, you should be able to see your image:
dotnet publishcan be used to push Docker images to remote registries, such as Azure Container Registry.
- The remote registry is configured in
- Publishing to remote registries usually requires authentication with
- Azure Container Registry authentication can be done using a custom Service Principal. This is the recommended approach for “headless” scenarios, such as CI build, but also can be used locally.