Docker basics: working with docker image registry

We had learnt how to build and run docker images, now it's the time for us to learn about share. The main point of sharing here is to push the docker image that we have in our local machine, and make it so other people can also use it. This is also an important feature of docker. This sharing feature makes not just you, but also everyone can use your image, run it on their local machine. There are no gaps between the machine and environment. If it runs on your machine, it will also run on their machine.

Working with docker image registry

What is a registry ? To answer this question, first, we have to know that when we run an image on our local machine, and we don't have that image locally, docker will have to download it from a server somewhere.

The server that store docker image centrally is called docker registry. The docker engine use docker hub as the default registry, which means that it will become the first place that docker will look for an image that isn't available locally.

Docker images need a name. Because how can docker find the exact image that we're looking for if the image doesn't have a name ? Docker image name sometimes consist of one or two parts, for example like express-app or cantdocpp/express-app. So, let's see the anatomy of docker image here:

docker.io/cantdocpp/golang:latest

docker.io is the domain of a registry which we store our image to. Docker hub is the default.

cantdocpp is the account of the image owner. It could be an individual user or an organization.

golang is the image repository name used for the application name. One repository can store many versions of the image.

latest* is the image tag used for versioning or defining application variation. Latest is the default tag.

As we can see that docker provides us some couple of defaults just in case we don't provide a value of an image reference. The default registry is docker hub and the default tag is latest.

If we use docker hub as our docker image registry, we don't have to specify the domain. For example, we can just type:

docker pull cantdocpp/golang:latest

And docker will search the docker hub as a default registry and pull it to our local machine. We don't even have to log in to docker hub, as we can pull any public image in docker hub.

Pushing docker image to the docker hub

In order to push docker images to the Docker hub, we'll be going to need docker hub account. So if you don't have an account, you can just register it in the docker hub.

We need to do two things to push an image to the Docker registry. First, we have to log in to the docker hub using the terminal or command line so docker can authorize whether the user has access to push the image. Secondly, we need to give a reference to an image that we're going to push that also includes the name of the account where we have permission to push.

So, we're going to login from the terminal/command line using this command:

docker login --username {yourusername}

After that docker will ask you to type your password (just in case, docker doesn't show you the password when you type in). If the login succeeds, you will get a response that says something like "login succeeded".

After that, we're going to give our local image that we're planning to push a new reference. Because our old local image doesn't have an account reference, then we're going to give it. Images can also have several references. Here's an example of how to give your local image a new reference:

docker image tag golang cantdocpp/golang:v1

So now we have one image with two references. The difference is, that one image has an account and version number in them. Let's check our image list now using this command:

docker image ls --filter reference=golang --filter reference='*/golang'

You'll see that the two images are having the same ID. And also, about the image size, you'll see that both of them also have the same size. But it's just the virtual size. In reality, both of those images share the same image layers as what we have learned here.

Now that we already have an image reference with our docker id that we use to log in to docker hub, we can start to push the image. Contrary to pull command that we use to download image to our local machine, this time we're going to use the push command. Here's the command:

docker image push cantdocpp/golang:v1

We've seen that we're using the new image that we've just created. We can also see that we've specified the account name, image name, and tags. So we have to make sure that we're really pushing the image that we've just created.

From our terminal/command line, we can see that in fact, docker is pushing image layers. So it's true that physically our image is just one thing, but in reality, our image composes of many layers. And this is the reason why we have to spend our time to optimize our Dockerfile here.

Layers that are uploaded to the registry if there isn't any matching layer hash for that layer in our image registry. For example, if we've pushed the same layers in the past to our registry, this time layers will not be pushed anymore. What exactly happened is, docker is listing all the layer hash in our registry, and if there's a match, it won't be pushed. It's like docker is saying "I only need this, this, and this. Because I already have this here".

After finish pushing. We can check the image in our docker hub account that we're used just now. If we don't have the repository for this image, docker hub will automatically create it for us. And by default, the repository will have a public rights.

Docker hub is also not the only registry available on the internet. Most of the clouds have their own registry service.