Create your own registry

In this tutorial, we’ll configure a raspberry pi to create a fully functional docker registry to push/pull your custom images.

The technologies used in this tutorial:

  • Raspberry Pi 4 model B

  • Debian 12 (bookworm)

  • Docker Registry using the registry docker image

  • Apache2 + certbot (Let’s encrypt) for HTTPS

  • Reverse proxy using Apache proxy modules

  1. Debian installation on the Raspberry PI

    Use Raspberry Pi Imager to flash and configure debian: https://www.raspberrypi.com/software/

    Note

    Make sure to enable SSH during configuration, you can also pre configure the wifi if you’re not planning to use an ethernet cable.

  2. Connection to the Raspberry PI

    If you enabled it during configuration you can use the following alias to connect:

    ssh <username>@raspberrypi.local # If enabled during configuration
    # OR
    ssh <username>@<ip-adress>
    
  3. Configure the DNS

    Modify the DNS so that it points to the IP adress where the Raspberry PI is connected to. In my case I added a A record on OVH for docker.algolisto.org pointing to my home IP adress.

  4. Install Apache2

    # Install Apache2
    sudo apt install apache2 -y
    # Enable required Apache2 modules
    a2enmod proxy* rewrite headers ssl
    
  5. Open port 443 and 80

    Get into your router configuration and open ports 443 (HTTPS) and 80 (HTTP) only for the Raspberry PI device.

  6. Check that you have access to the default Apache2 page using HTTP (in my case: http://docker.algolisto.org) (if the DNS has been updated)

  7. Enable HTTPS using Let's encrypt and certbot

    # Install Certbot and Apache Plugin
    sudo apt install certbot python3-certbot-apache
    # Obtain and Install a Certificate
    sudo certbot --apache -d docker.algolisto.org
    # View Installed Certificates
    sudo certbot certificates
    # Check Certbot Timer Status
    systemctl status certbot.timer
    # Test Certificate Renewal
    certbot renew --dry-run
    
  8. Check that you have access to the default Apache2 page using HTTPS (in my case: https://docker.algolisto.org)

  9. Start the docker registry local server

    sudo mkdir -p /data/docker-registry
    docker run -d \
        --name docker-registry \
        --restart always \
        -p 127.0.0.1:8080:5000 \
        -v /data/docker-registry:/var/lib/registry \
        registry:2
    

    Note

    Port 8080 on 127.0.0.1 loopback address is forwarding the request to the container on port 5000 (the default port for the registry)

  10. Create a user/password for access to the docker registry

    # Create a file /etc/apache2/htpasswd with an entry for the user "docker" and the hashed MD5 password
    cd /etc/apache2
    sudo htpasswd -c -m htpasswd docker
    
  11. Edit the Apache configuration

    Edit the file: /etc/apache2/sites-enabled/000-default-le-ssl.conf

    <IfModule mod_ssl.c>
        <Location "/">
            # Access Control with IP Restriction
            Order deny,allow
            Deny from all
            Allow from 87.104.201.45
            Satisfy all
    
            # Authentication
            AuthUserFile /etc/apache2/htpasswd
            AuthName "Authentication"
            AuthType Basic
    
            require valid-user
        </Location>
        <VirtualHost *:443>
            ServerAdmin webmaster@localhost
            ErrorLog ${APACHE_LOG_DIR}/error.log
            CustomLog ${APACHE_LOG_DIR}/access.log combined
    
            # Certificates path
            ServerName docker.algolisto.org
            SSLCertificateFile /etc/letsencrypt/live/docker.algolisto.org/fullchain.pem
            SSLCertificateKeyFile /etc/letsencrypt/live/docker.algolisto.org/privkey.pem
    
            # Additional SSL/TLS-related configuration options provided by Let's Encrypt
            Include /etc/letsencrypt/options-ssl-apache.conf
    
            # Custom headers added to indicate compatibility with Docker Registry API version 2.0
            Header always set "Docker-Distribution-Api-Version" "registry/2.0"
            Header onsuccess set "Docker-Distribution-Api-Version" "registry/2.0"
    
            # Ensures that the backend server is aware that the original request was made over HTTPS
            RequestHeader set X-Forwarded-Proto "https"
    
            # Reverse Proxy to the Backend Server (docker registry)
            ProxyPreserveHost On
            ProxyPass / http://127.0.0.1:8080/
            ProxyPassReverse / http://127.0.0.1:8080/
        </VirtualHost>
    </IfModule>
    

    Note

    In the file above you need to adapt the following lines to your need:

    • Allow from 87.104.201.45

    • ServerName docker.algolisto.org

    • SSLCertificateFile /etc/letsencrypt/live/docker.algolisto.org/fullchain.pem

    • SSLCertificateKeyFile /etc/letsencrypt/live/docker.algolisto.org/privkey.pem

    Note

    You can get the path of the certificates using the command sudo certbot certificates

  12. Check the validity of the apache configuration

    sudo apache2ctl configtest
    
  13. Check pushing/pulling an image to/from your repository from another machine

    docker login docker.algolisto.org
    # set the user and password you created earlier
    docker pull hello-world
    docker tag hello-world:latest docker.algolisto.org/hello-world:latest
    docker push docker.algolisto.org/hello-world:latest
    docker pull docker.algolisto.org/hello-world:latest
    

Sources: