Docker - Private Registry

Table of Contents

One of the things that makes Docker so helpful is how easy it is to pull ready-to-use images from Docker's Central Registry, a central location. Pushing your own image (or tagged image collection as a repository) to the same public registry is just as easy, so that everyone can benefit from your new Dockerized service.

But sometimes, as it contains proprietary code or confidential information, you can't share your repository with the world. We are introducing an easy way to share repositories on your own registry today so that you can control access to them and still share them among multiple daemons from Docker. If your registry is public or private, you can decide.

an image can be pushed to the Docker Hub by using the follwoing command:

docker push repository/my-image

and to push an image to a private registry first we must tag the image based on that registry then push it:

docker tag my-image:latest my-private-remote-registry/my-image:latest
docker push my-private-remote-registry/my-image:latest

In addition to pushing the image directly, it is also possible to send only the dockerfile. The Docker Hub has the capability to automatically build the image from Dockerfile kept in the repository of GitHub or Bitbucket.

Automated builds are supported on both private and public repositories of GitHub and Bitbucket. The Docker Hub Registry keeps all the automated build images.

Private Repositories

Normally, enterprises will not like to keep their Docker images either in a Docker public or private repository. They prefer to keep, maintain, and support their own repository. Hence, Docker also provides the option for enterprises to create and install their own repository. To create a repository in the local machine using the registry image provided by Docker, we can run the registry container on the local machine, using the registry image from Docker:

$ docker run --name registry -p 5000:5000 -d registry 

Push images

You can pull an image from Docker Hub and push it to your registry in the follwoing steps:

  1. Pull the image from Docker Hub.
$ docker pull image-name
  1. Tag the image as localhost:5000/my-image-name. This creates an additional tag for the existing image. When the first part of the tag is a hostname and port, Docker interprets this as the location of a registry, when pushing.
$ docker tag image-name localhost:5000/my-image-name
  1. Push the image to the local registry running at localhost:5000:
$ docker push localhost:5000/my-image-name

Start the registry automatically

If you want to use the registry as part of your permanent infrastructure, you should set it to restart automatically when Docker restarts or if it exits. This example uses the --restart always flag to set a restart policy for the registry.

$ docker run -d -p 5000:5000 \
    --restart=always --name registry registry:2

Customize the published port

If you are already using port 5000, or you want to run multiple local registries to separate areas of concern, you can customize the registry’s port settings. This example runs the registry on port 5001 and also names it registry-test. Remember, the first part of the -p value is the host port and the second part is the port within the container. Within the container, the registry listens on port 5000 by default.

$ docker run -d -p 5001:5000 \
  --name registry-test registry:2

Customize the storage location

By default, your registry data is persisted as a docker volume on the host filesystem. If you want to store your registry contents at a specific location on your host filesystem, such as if you have an SSD or SAN mounted into a particular directory, you might decide to use a bind mount instead. A bind mount is more dependent on the filesystem layout of the Docker host, but more performant in many situations. The following example bind-mounts the host directory /mnt/registry into the registry container at /var/lib/registry/.

$ docker run -d  -p 5000:5000 \
    --restart=always  --name registry \
    -v /mnt/registry:/var/lib/registry registry:2

Externally-accessible registry

Running a registry only accessible on localhost has limited usefulness. In order to make your registry accessible to external hosts, you must first secure it using TLS.

Assume we have the following condition/requirements:

  • Your registry URL is
  • Your DNS, routing, and firewall settings allow access to the registry’s host on port 443.
  • You have already obtained a certificate from a certificate authority (CA).

First of all we need to create SSL certificate and copy it ot a directory e.g. certs This command bind-mounts the certs/ directory into the container at /certs/, and sets environment variables that tell the container where to find the domain.crt and domain.key file. The registry runs on port 443, the default HTTPS port.

$ docker run -d \
  --restart=always \
  --name registry \
  -v "$(pwd)"/certs:/certs \
  -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
  -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
  -p 443:443 \


  1. Build a image using debian as base image and tag it with my-image.
  2. create a private registry: docker run --name registry -p 5000:5000 -d registry
  3. push the image to the private registry:
docker tag my-image localhost:5000/my-image 
docker push localhost:5000/my-image