Quick Links

Running your own Docker registry gives you a private place to store your Docker images. Whether you're in a corporate environment or just want to reduce your reliance on Docker Hub, here's how you can get up and running with a registry deployment.

Docker Registry is a server-side system that stores and indexes Docker images. You "push" prebuilt images into the registry. Other users can then "pull" them down to run them, without needing access to the original Dockerfile.

The best known public registry is Docker Hub. Using your own registry lets you take control of image storage and access methods. It can also facilitate integration with third-party tools.

There are managed services available that let you quickly create registry installations. This guide focuses on self-hosting a registry on your own server. The only prerequisites are you'll need to have Docker and docker-compose installed on the machine which will host the registry.

Running a Registry

The Docker Registry server is distributed as its own Docker image. You can get it from Docker Hub. The server is exposed on port 5000; you'll need to bind a host port to it so that clients can connect.

You must also set up a volume so Docker Hub has somewhere to persistently store uploaded images. Make sure you've got sufficient free space on your host. An actively used registry can quickly grow.

Begin by creating a docker-compose.yml file to describe your deployment. You can adjust the ports and filesystem paths to match your preferences. This example will make the registry accessible on port 5000. Images will be stored in the data folder within your working directory.

version: "3"
    

services:

registry:

image: registry:2

ports:

- 5000:5000

environment:

- REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data

restart: unless-stopped

volumes:

- ./data:/data

Save the file and run

        docker-compose up -d
    

to launch your registry. docker-compose will pull the registry image from Docker Hub. It'll then start a new container using your configuration.

Accessing Your Registry

You should now be able to start using your registry. Tag an image using a path which resolves to your registry. You can use localhost if you're working on the registry server itself. You should then be able to push the image up to the registry.

docker tag my-image localhost:5000/my-image
    

docker push localhost:5000/my-image

The image will now be available in the registry. If you inspect your data folder, you'll see the layers that make up the image. You could pull it down from another machine by using docker pull. Replace localhost with the network address of the server running the registry.

Setting up Authentication

The registry is currently unsecured. Anyone can pull and push images! Let's resolve that by setting up authentication. Once configured, you'll need to use docker login before you can interact with the registry.

Docker Registry's default approach to authentication uses HTTP Basic Auth. You'll need to create an htpasswd file - this is best done using the command provided by apache2-utils.

sudo apt install apache2-utils
    

mkdir auth

htpasswd -Bc auth/.htpasswd my-username

This will create an authentication file for the user my-username. You'll be prompted to supply a password. The htpasswd file will then be written into the working directory as auth/.htpasswd.

Next update your docker-compose.yml to configure the authentication system. You must specify the type of authentication used and the path to the htpasswd file. This will need to be mounted as a new volume.

version: "3"
    

services:

registry:

image: registry:2

ports:

- 5000:5000

environment:

- REGISTRY_AUTH: htpasswd

- REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm

- REGISTRY_AUTH_HTPASSWD_PATH: /auth/.htpasswd

- REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data

restart: unless-stopped

volumes:

- ./auth:/auth

- ./data:/data

Run docker-compose up -d --force-recreate to recreate the running registry container using the new configuration. You should find the Docker CLI now refuses to let you interact with the registry.

To restore access, run docker login localhost:5000. You'll need to adjust the registry URI if you're not running Docker on the same machine. Docker will prompt you to supply your username and password. Use the values you set while creating the .htpasswd file.

Once authentication succeeds, you'll be able to start pushing and pulling images again. Docker caches your credentials so you won't need to repeat authentication until you docker logout.

Setting Up SSL

You'll need to add a SSL certificate for all but the most basic connections over localhost. You can add an SSL certificate to the registry by mounting the certificate into a volume and setting additional environment variables. You should usually update the port configuration so the registry listens on 443, the default HTTPS port.

version: "3"
    

services:

registry:

image: registry:2

ports:

- 443:5000

environment:

- REGISTRY_AUTH: htpasswd

- REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm

- REGISTRY_AUTH_HTPASSWD_PATH: /auth/.htpasswd

- REGISTRY_HTTP_ADDR: 0.0.0.0:443

- REGISTRY_HTTP_TLS_CERTIFICATE=/certs/cert.crt

- REGISTRY_HTTP_TLS_KEY=/certs/cert.key

- REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data

restart: unless-stopped

volumes:

- ./auth:/auth

- ./certs:/certs

- ./data:/data

Add your certificate files to certs and then restart the registry. It should come back up with HTTPS support, using the provided certificate file.

SSL via LetsEncrypt

The Registry server has built-in support for Let's Encrypt. This lets you automatically generate and renew your SSL certificates. To use Let's Encrypt, you must publicly expose your registry on port 443.

Set the REGISTRY_HTTP_TLS_LETSENCRYPT_EMAIL and REGISTRY_HTTP_TLS_LETSENCRYPT_HOSTS environment variables to add TLS support to your registry. Let's Encrypt will use the email address as the contact for your SSL certificates.

version: "3"
    

services:

registry:

image: registry:2

ports:

- 443:5000

environment:

- REGISTRY_AUTH: htpasswd

- REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm

- REGISTRY_AUTH_HTPASSWD_PATH: /auth/.htpasswd

- REGISTRY_HTTP_TLS_LETSENCRYPT_EMAIL: example@example.com

- REGISTRY_HTTP_TLS_LETSENCRYPT_HOSTS: [my-registry.com]

- REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data

restart: unless-stopped

volumes:

- ./auth:/auth

- ./certs:/certs

- ./data:/data

Recreate the container with docker-compose up -d --force-recreate to apply the change. The registry will use Let's Encrypt to acquire an SSL certificate for the specified domains. It might take a few minutes for the certificate to become available.

Other Ways to Deploy

Deploying with docker-compose, HTTP Basic Auth and Let's Encrypt is the simplest way of running a private container registry. There are other options available though, particularly if you want more advanced access control.

Using Basic Auth doesn't scale well beyond a handful of users. As an alternative, the server supports a delegated authentication routine that relies on external token servers. This is designed for scenarios where tight integration with organisational access control systems is required.

The Registry server doesn't implement token authentication itself. Projects such as docker_auth try to add this missing piece, providing a fully-fledged auth system that can be deployed alongside the main registry.

Alternative projects aim to make it easier to manage your registry, without resorting to hands-on terminal commands. Portus is a SUSE project which provides a web frontend, as well as its own user authentication system.