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
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
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
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
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
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.
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: firstname.lastname@example.org - 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.