How to setup a Private Docker Registry on Ubuntu / Debian

Set Up a Private Docker Registry on Ubuntu 22.04 / debian

Introduction

Docker Registry is a powerful tool that helps manage the storage and distribution of Docker container images. While Docker Hub provides a free public registry for hosting custom Docker images, there are scenarios where it is necessary to have a private registry to keep sensitive or proprietary images secure. By setting up a private Docker Registry, developers can have full control over their container images and restrict access to authorized users.

In this tutorial, we will walk you through the process of setting up and securing your own private Docker Registry on an Ubuntu 22.04 / 20.04 / 18.04 server. You will learn how to configure Docker Compose to define the registry’s settings and use Nginx to forward traffic from the internet to the running Docker container. By the end of this tutorial, you will be able to push and pull Docker images securely from your private registry.

Prerequisites

To follow along with this tutorial, you will need the following:

  • Two Ubuntu / Debian servers: one will act as the host server for your private Docker Registry, and the other will serve as the client server.
  • Docker installed on both servers. You can refer to the tutorial on How To Install and Use Docker on Ubuntu 18.04/20.04/22.04 LTS for detailed instructions on setting up Docker.
  • Docker Compose installed on the host server.
  • Nginx installed on the host server.
  • Nginx secured with Let’s Encrypt on the host server.
  • A registered domain name that resolves to the server hosting your private Docker Registry. You will set this up as part of the Let’s Encrypt prerequisite. For the purposes of this tutorial, we will refer to this domain as your_domain.

Step 1: Installing and Configuring the Docker Registry

To start, we need to set up the Docker Registry using Docker Compose. Docker Compose allows you to define and manage the configuration of your Docker containers easily.

  • Connect to your host server via SSH.
  • Create a directory called docker-registry to store the configuration files by running the following command:
$ mkdir ~/docker-registry
  • Navigate to the newly created directory:
cd ~/docker-registry
  • Create a subdirectory called data to store the Docker Registry’s images:
$ mkdir data
  • Create a docker-compose.yml file and open it for editing:
$ nano docker-compose.yml
  • Add the following content to the docker-compose.yml file to define a basic instance of the Docker Registry:
version: '3'
services:
  registry:
    image: registry:latest
    ports:
      - "5000:5000"
    environment:
      REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
    volumes:
      - ./data:/data

This configuration sets up a Docker Registry service called registry, using the registry:latest image. It maps port 5000 on the host to port 5000 in the container. The REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY environment variable specifies the directory where the images will be stored within the container. Finally, it mounts the ./data directory on the host to the /data directory in the container to persist the image data.

  • Save and close the file by pressing Ctrl + X, followed by Y, and then Enter.
  • Start the Docker Registry service by running the following command:
$ docker-compose up -d

The -d flag runs the containers in the background.

At this point, your private Docker Registry is up and running on your host server. The registry is accessible via the domain name or IP address of your server on port 5000.

Step 2: Configuring Nginx as a Reverse Proxy

To securely access the Docker Registry over HTTPS and route traffic from the internet to the registry container, we’ll use Nginx as a reverse proxy. The reverse proxy will handle SSL termination and forward requests to the Docker Registry service.

  • Connect to your host server via SSH.
  • Open the Nginx configuration file for your domain using the following command (replace your_domain with your registered domain name):
$ sudo nano /etc/nginx/sites-available/your_domain
  • Remove the existing contents and add the following configuration:
server {
    listen 80;
    listen [::]:80;
    server_name your_domain;
    return 301 https://$host$request_uri;
}
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name your_domain;
    ssl_certificate /etc/letsencrypt/live/your_domain/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your_domain/privkey.pem;
    location / {
        proxy_pass http://localhost:5000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Replace your_domain with your registered domain name. This configuration sets up Nginx to redirect HTTP requests to HTTPS and listens for incoming HTTPS requests. It specifies the SSL certificate and key locations provided by Let’s Encrypt. The location / block proxies requests to http://localhost:5000, which corresponds to the Docker Registry service running on the host.

  • Save and close the file by pressing Ctrl + X, followed by Y, and then Enter.
  • Enable the Nginx configuration by creating a symbolic link:
$ sudo ln -s /etc/nginx/sites-available/your_domain /etc/nginx/sites-enabled/
  • Test the Nginx configuration for syntax errors:
$ sudo nginx -t

If the configuration file has no syntax errors, you will see syntax is ok and test is successful messages.

  • Restart Nginx to apply the changes:
$ sudo systemctl restart nginx

Nginx is now configured as a reverse proxy for your Docker Registry, handling SSL termination and forwarding requests to the registry service.

Step 3: Pushing and Pulling Images from the Private Docker Registry

Now that your private Docker Registry is set up and accessible via your domain name over HTTPS, you can push and pull Docker images to and from the registry.

To push an image to the registry, use the following command:

$ docker push your_domain/image_name:tag

Replace your_domain with your registered domain name, image_name with the name of your image, and tag with a specific version or tag for the image.

To pull an image from the registry, use the following command:

$ docker pull your_domain/image_name:tag

Again, replace your_domainimage_name, and tag with the appropriate values.

Step 4: Enable Authentication

By default, the Docker Registry we set up does not require authentication for pushing and pulling images. However, enabling authentication adds an extra layer of security to your private Docker Registry. With authentication enabled, only authorized users will be able to access and interact with the registry.

To enable authentication, you can choose from several authentication methods depending on your requirements. One common method is to use a username and password-based authentication system. Docker Registry supports a basic authentication mechanism using an htpasswd file. Here’s how you can enable authentication:

Create an htpasswd file:

  • Install the apache2-utils package if not already installed:
$ sudo apt-get install apache2-utils
  • Generate an htpasswd file with a username and password:
$ sudo htpasswd -Bc /path/to/htpasswd <username>
  • You will be prompted to enter and confirm the password for the specified username. Repeat this step for each user you want to add.

Configure Docker Registry to use authentication:

  • Open your docker-compose.yml file.
  • Add the following environment variable to the registry service:
environment:
  - REGISTRY_AUTH=htpasswd
  - REGISTRY_AUTH_HTPASSWD_PATH=/path/to/htpasswd
  - REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm
  • Replace /path/to/htpasswd with the actual path to your htpasswd file.

Save the changes and restart the Docker Registry:

$ docker-compose down
$ docker-compose up -d

Once authentication is enabled, users will need to provide valid credentials (username and password) to push and pull images from the registry.

Remember to manage user accounts and passwords securely. Regularly review and update user access as necessary. You can also explore other authentication methods such as token-based authentication or integrating with external authentication providers like LDAP or OAuth.

That’s it! You now have your own private Docker Registry set up with SSL encryption and accessible via a domain name. You can use this registry to securely store and manage your Docker images.

Conclusion:

In this article, we discussed the process of setting up a private Docker Registry. We covered the installation of Docker , creating a Docker Compose file, enabling SSL/TLS encryption, and enabling authentication for authorized access. By following these steps, you can establish a secure Docker Registry to manage and distribute your containerized applications within your organization. Remember to stay updated on security best practices and regularly review your registry’s configuration. Enjoy the benefits of a well-secured Docker Registry for streamlined application deployment.

LEAVE A COMMENT