1. Overview

This tutorial will demonstrate how to push a Docker image to a self-hosted Docker registry. First, we’ll explore what a self-hosted registry is and how it’s different from a public one. We’ll then learn how to tag images that we want to push to a self-hosted registry. Finally, we’ll see how to actually push those images.

2. Self-Hosted Docker Registries

A Docker registry is a service that manages container image repositories. It allows us to do things like create repositories, push and pull images, and manage repository access. While many registries are provided as cloud services, registries may also be self-hosted.

When a registry is provided via the cloud, we don’t have to care about its hosting and maintenance. We simply have to register with the service and then use the provided functionality. Cloud-hosted Docker registries are also called public registries. Docker Hub is a well-known example of a public registry.

If a company has special requirements, however, public registries might not be an option. Companies that cannot use public registries often have self-hosted ones that they can customize to their requirements. For example, a company might have a privacy policy requiring repositories to only be accessible via the company’s internal network. Or a company might need to run specific vulnerability scans on its images.

3. Tagging Images for Self-Hosted Registries

We must tag images in a particular way before we can push them to a self-hosted registry. Let’s learn how to tag images appropriately.

3.1. The Image Name Pattern

When pushing an image, the image name defines where the image will be pushed. This is why, in order to push an image to a self-hosted registry, it’s crucial that we use the correct naming pattern. The image name must contain the registry host, the port, and the repository name, and can optionally be followed with a version tag:

[registry host]:[registry port]/[repository name]:[tag name]

Suppose we have a registry that is running on localhost and listening on port 5000. Here’s an example name for version 1.0.0 of an image that we want to push to the my-fancy-app repository in that registry:


We’ll use this example throughout the rest of this article.

Now that we know what naming pattern to apply, we can prepare an image for our self-hosted registry. First, we’ll see how to build a new image with the correct name. Then we’ll learn how to prepare an existing image by renaming it.

3.2. Tagging a New Image

If we’re building a new image and already have an application and Dockerfile prepared, we can use the -t flag of the docker build command so the image will be created with the appropriate name. Using the example from the previous section, the command would be:

$ docker build -t localhost:5000/my-fancy-app:1.0.0 .

This tags the new image with the correct name followed by the optional version tag. The dot “.” at the end of the line indicates that we’re executing the command in the same directory as our Dockerfile.

3.3. Re-Tagging an Existing Image

If we want to push an existing image to our self-hosted registry, we first need to tag the image with a new alias that matches the naming pattern that we described above. We can re-tag an image with the docker tag command:


For example, suppose we want to push an existing image called my-fancy-app:1.0.0 to our self-hosted registry. We would simply use the docker tag command to tag it with a new alias that matches that registry:

$ docker tag my-fancy-app:1.0.0 localhost:5000/my-fancy-app:1.0.0

4. Pushing the Image

Once we’ve properly tagged an image, we can push it to our self-hosted registry.

Companies often require authentication to protect their self-hosted registries. When that’s the case, we first need to log in with the docker login command:

docker login [OPTIONS] [SERVER]

For our self-hosted registry that’s hosted on localhost:5000, the command is:

$ docker login localhost:5000

After logging in, we use the docker push command to push an image to our self-hosted registry:

docker push [OPTIONS] NAME[:TAG]

Let’s see the command to push the image we prepared in the sections above:

$ docker push localhost:5000/my-fancy-app:1.0.0

5. Verifying the Push

The last step is to verify that the image is now available in our self-hosted registry. To do that, we’ll pull the image from that registry, but we must first delete our cached local image by running the docker image rm command:

$ docker image rm localhost:5000/my-fancy-app:1.0.0

Let’s verify we removed the image by listing all of our local images and checking that our image isn’t there:

$ docker images

Next, let’s pull the image from our self-hosted registry using the docker pull command:

$ docker pull localhost:5000/my-fancy-app:1.0.0

By listing all local images again, we can verify that our image was successfully pulled from our self-hosted registry:

$ docker images
REPOSITORY                  TAG   IMAGE ID     CREATED        SIZE 
localhost:5000/my-fancy-app 1.0.0 d33a5b65c0f5 20 minutes ago 326MB

6. Conclusion

In this article, we’ve learned what self-hosted Docker registries are and why we might use them. We’ve also explored how to prepare an image – whether it’s a pre-existing image or a new one we’re building – so that we can push it to a self-hosted registry. Finally, we learned how to push the properly-tagged image to our example registry.

Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.