Tuesday, January 5, 2021

Pushing Docker images to ACR - Azure Container Registry

Building ASP.NET Core websites with Docker? Learn how to use Azure Container Registry.
Photo by Hal Gatewoodon on Unsplash

Since you now understand how to create your own ASP.NET Core websites with Docker, the next step in your container journey is learning how to push your images to a container registry so they can be shared and deployed somewhere else.

Today, we will push our own ASP.NET Core Docker images to Azure's Container Registry (ACR) and deploy them to our own custom CentOS server. Sounds complicated? Let's see.

On this post we will:
  • (Quickly review how to) Create our own Docker images.
  • Create our Azure Container Registry to host and share our images.
  • Push our own Docker images to our new container registry.
  • Pull and run our images from a CentOS server.


For this post you'll need:

Managed Container Registries

Today, Docker Hub is still the world's most popular container registry. But do you know what container registries are? I like this definition from GCP:
A Container Registry is a single place for your team to manage Docker images, perform vulnerability analysis, and decide who can access what with fine-grained access control. Existing CI/CD integrations let you set up fully automated Docker pipelines to get fast feedback.

Why create our own container registry?

Okay but if we already have Docker Hub, why bother creating our own container registry?

Because as we will see, pushing our images to a managed container registry allows you to not only share your images privately with other developers in your organization but also to utilize them in your CI/CD - in an integrated fashion -, process and deploy them to your cloud resources such as Virtual Machines, Azure App Services and even Azure Kubernetes Services.

In summary, the main advantages of creating our own container registry are:
  • have our own private repository
  • use it as a source of deployment for our artifacts, especially if on the same cloud
  • integrate with your CI/CD process to produce automated pipelines
  • use a cloud-hosted service, alleviating our ops team
  • have automated vulnerability scans for our own images
  • geo-distribute your images so teams around the globe can access them quickly

Alternatives to ACR (Azure Container Registry)

But what if you use a different cloud? No problem! Apart from ACR and Docker Hub today we also have: Amazon ECS, Red Hat's QuayGoogle Container Registry (GCR) and Digital Ocean's Container Registry.

And which registry should I choose? I'd recommend using the one offered by your cloud provider since they will have better integration with resources on your cloud resources. In other words, on AWS? use ECS. On Google Cloud? Use GCR. On Azure, go with ACR. Else, stick with Docker Hub.

Creating our Azure Container Registry

So let's get to work. There are essentially two ways to create our own registry on Azure: via the CLI and via the portal. Since the Azure CLI alternative is already very well documented, let's review how to do it from the portal.

Click New Resource, type Container Registry and you should see:

Click Create, enter the required information:
Review and confirm, the deployment should take a few seconds:

Reviewing our Container Registry

Once the deployment finishes, accessing your own container registry should get you to a panel similar to the below. In yellow I highlighted my registry's URL. We'll need it to push our images.

I like pinning resources by project on a custom Dashboard. Fore more information, check this link.

Preparing our Image

Let's now prepare an image to push to the remote registry. I'll use my own available on GitHub but feel free to use yours if you already have one available.

Pulling a sample .NET image

If you followed my previous post on how to create ASP.NET Core websites using Docker, you probably have our webapp ASP.NET Core 3.1 image on your Docker repository. If not, please run:
git clone https://github.com/hd9/aspnet-docker
cd aspnet-docker
docker build . -t webapp
Then type the below command to confirm your image is available locally:
docker image ls
docker images or docker image ls? Both are the same but since all commands to manage images use the docker image prefix I prefer to follow that pattern. Feel free to use what suits you better.

Tagging our image

Before pushing our image we still need to tag it with the full repo name and add a reasonable version to it:
docker tag webapp <acrname>.azurecr.io/webapp:v1
You have to tag the image with the fully qualified domain name (ex. yourrepo.azurecr.io) in the name else, Docker will try to push it to Docker Hub.

Run docker image ls once more to make sure your image is correctly tagged:

Pushing our Image

With the image ready, let's push it to our registry.

Logging in to our Registry

The first thing we'll need is to authenticate using the Azure CLI. On a Windows terminal, type:
az acr login --name <your-acr-name>
if you used the az tool before, you're probably logged in and you won't be required to enter any username/password. Else, you'll need to sign in with the az login command then sign in again with az acr login. Check this page for more details.

Now the big moment. Push the image to the remote repo with:
docker push <acrname>.azurecr.io/webapp:v1
If all went well, you should see on the Services/Repositories tab, our image webapp as a repository:
And clicking on our repo, we see v1 as Tag and additional info about our image on the right:

Deploying our image locally

Pulling and running your remote image locally should be really simple since tools/credentials are in place. Run:

docker pull hildenco.azurecr.io/webapp:v1
docker run -d webapp

Deploying our image to a remote Linux VM

But we're here to learn so let's complicate this a little and deploy this image to a remote Linux VM. For this part of the tutorial, make sure your VM is ready by installing the following requirements:
To avoid sudoing all the time with Docker, add your user to the docker group with sudo usermod -aG <username>

Authenticating with the Azure CLI

If you recall, we had to login to our repo from our development box. Turns out that our CentOS VM is another host so we'll have to login again first with the main az login:
az login
Then login on ACR:
az acr login --name <your-acr-name>

Pulling our Image from CentOS

With the authentication in place, pulling the image from our CentOS should be familiar:
docker pull hildenco.azurecr.io/webapp:v1

Running our Container

The last step is to run our image and access it from outside. To run our image we do:
docker run --rm -d -p 8080:80 hildenco.azurecr.io/webapp:v1
  • --rm: remove container when stopped
  • -d: run in detached (background) mode
  • -p 8080:80: map port 80 on container to external 8080 on host

Accessing our Container

Then, accessing from outside requires knowing the VM's IP address and accessing it from the development box (host). To know your CentOS's IP, type:
ip a show eth0
 Then, with the IP, access it from your favourite browser:


On this article we described how to create our own Azure's Container Registry on Azure, push, pull and deploy images from it to a CentOS virtual machine. With the growth of microservices, knowing Docker becomes an essential skill these days. And since containers are the way developers build, pack and ship applications these days, knowing how to use a managed container registry will be an essential asset for your team.

Source Code

As always, the source code for this post is available on my GitHub.


See Also

About the Author

Bruno Hildenbrand      
Principal Architect, HildenCo Solutions.