Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / containers / docker

How to Secure Your Private Docker Registry?

4.00/5 (1 vote)
17 Oct 2018CPOL5 min read 20K  
Step by step guide to apply the SSL and basic authentication to the Docker registry

Introduction

In my previous article, I explained how to set up your private Docker registry in your local machine with the Docker Registry tool. All features work fine when you are consuming the private registry from the host machine but the problem will start when you try to access from the remote machine, the docker will throw an error about https connection. Also, it is mandatory to secure your private registry when it accessible through public networks. In this article, we are going to see what are all the possible options we have and how to use them.

This is the second part of my private Docker Registry series and the following list shows the outline of the series:

Securing the Private Registry

We have three security options to secure your private registry and we are going to cover all three options in this article. The available options are:

  • Enabling the SSL with CA Certificate
  • Enabling the SSL with Self-Signed Certificate
  • Basic Authentication

CA Certificate

To enable the https in a web server, we need an SSL certificate against our domain name (for our example hub.docker.local). There are lots of CAs out there in the market to provide these certificates. For a production environment, it is recommended to use the SSL certificate from CAs instead of creating your own. Docker registry supports using Let's Encrypt (open source CA) so you can think of using this as well. Assume you have received the required SSL certificates (hub.docker.local.crt, hub.docker.local.key) from your CA vendor for the hub.docker.local domain and now you're ready to configure SSL for your private registry.

Do the following steps to configure SSL to your private registry:

  • Open a PowerShell console (terminal in Linux)
  • Navigate to C:\localhub folder (remember we created this folder in the previous article). For Linux, go to /home/localhub.
  • Create certs folder
  • Copy your certificate files hub.docker.local.crt, hub.docker.local.key into certs folder
  • Spin up a container for registry with your SSL certificates
    BAT
    Windows:
    docker run -d -p 443:443 --name local.hub -v C:/localhub/certs:/certs 
    -v C:/localhub/registry:/var/lib/registry -e REGISTRY_HTTP_ADDR=0.0.0.0:443 
    -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/hub.docker.local.crt 
    -e REGISTRY_HTTP_TLS_KEY=/certs/hub.docker.local.key registry
    
    Linux:
    docker run -d -p 443:443 --name local.hub -v /home/localhub/certs:/certs 
    -v /home/localhub/registry:/var/lib/registry -e REGISTRY_HTTP_ADDR=0.0.0.0:443 
    -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/hub.docker.local.crt 
    -e REGISTRY_HTTP_TLS_KEY=/certs/hub.docker.local.key registry
  • Ensure your registry container is up and running:
    BAT
    Windows/Linux:
    docker container ls
  • Repeat the same steps from the previous article to push & pull an image from your private registry:
    BAT
    Windows/Linux:
    docker pull alpine
    docker tag alpine hub.docker.local/alpine
    docker push hub.docker.local/alpine
    docker rmi hub.docker.local/alpine
    docker images
    docker pull hub.docker.local/alpine
    docker images

    Image 1

  • Also, check the catalog URL https://hub.docker.local/v2/_catalog with a browser to ensure your registry returning the metadata

Self-Signed Certificate

It is strongly not recommended to use a self-signed certificate for production however, we can use this for testing purposes and understanding the capability of SSL. To use the self-signed certificate, we need to do the following things:

  • Configure a local DNS entry
  • Generate self-signed certificate
  • Apply the self-signed certificate to the registry

Configure a Local DNS Entry

At the beginning of the previous article, we have seen how to configure the local DNS entry for hub.docker.local. Please refer to it and we are going to use the same.

Generate Self-Signed Certificate

We are going to use OpenSSL to generate the self-signed certificates. For Linux, OpenSSL comes with part of application repository so you can easily pull it through apk if it is not installed already. For Windows, you need to download and install manually from this links 64 bit/32 bit.

Windows Installation
Download the appropriate OpenSSL installer for your CPU architecture and it is recommend to choose the bin folder to extract binary files instead of System 32 folder. Once installation is done, add the openssl installed bin folder to PATH environment variables.

Do the following steps to generate the self-signed certificate:

  • Open a PowerShell console(terminal in Linux).
  • Navigate to C:\localhub folder (remember we created this folder in the previous article). For Linux, go to /home/localhub.
  • Create certs folder.
  • Type the following command to generate the self-signed certificate:
    BAT
    Windows/Linux:
    openssl req -newkey rsa:4096 -nodes -sha256 -keyout certs/localhub.key -x509 
    -days 365 -out certs/localhub.crt
  • Once you hit the enter key, it will ask you a series of questions. Answer appropriately for all questions except Common Name. Common Name should exactly match with your local domain name, for our example, it is hub.docker.local.

    Image 2

  • Congratulations! You have created a self-signed certificate for your local domain.

Apply the Self-Signed Certificate to the Registry

Just repeat the same steps that you followed in applying CA certificate with newly created certificate files.

  • Spin up a container for registry with your self-signed SSL certificates:
    BAT
    Windows:
    docker run -d -p 443:443 --name local.hub -v C:/localhub/certs:/certs 
    -v C:/localhub/registry:/var/lib/registry -e REGISTRY_HTTP_ADDR=0.0.0.0:443 
    -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/localhub.crt 
    -e REGISTRY_HTTP_TLS_KEY=/certs/localhub.key registry
    
    Linux:
    docker run -d -p 443:443 --name local.hub -v /home/localhub/certs:/certs 
    -v /home/localhub/registry:/var/lib/registry -e REGISTRY_HTTP_ADDR=0.0.0.0:443 
    -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/localhub.local.crt 
    -e REGISTRY_HTTP_TLS_KEY=/certs/localhub.key registry
  • Ensure your registry container is up and running:
    BAT
    Windows/Linux:
    docker container ls
  • Do the image push & pull from your private registry with following commands:
    BAT
    Windows/Linux:
    docker pull alpine
    docker tag alpine hub.docker.local/alpine
    docker push hub.docker.local/alpine
    docker rmi hub.docker.local/alpine
    docker images
    docker pull hub.docker.local/alpine
    docker images

    Image 3

  • Check the catalog URL https://hub.docker.local/v2/_catalog with a browser to ensure your registry returning the metadata. This time, you receive a warning about an invalid certificate.

Basic Authentication

So far, we have seen how to share your private registry images securely across the networks and it is also important to consider how to restrict the access to the content. In this section, we are going to how to set up the user authentication to your private registry. Do the following steps to enable the user authentication to your private registry,

  • Open a PowerShell console (terminal in Linux)
  • Navigate to C:\localhub folder (remember we created this folder in the previous article). For Linux, go to /home/localhub
  • Create auth folder
  • Type the following command to generate the user profile file:
    BAT
    Windows/Linux:
    docker run --entrypoint htpasswd registry -Bbn iniyan pass123
    
    It seems windows docker having issue when directly write the output into a file, 
    to avoid the issue copy the console output of above command without any space 
    and paste to a notepad, save to htpasswd(without any extension) file under C:\localhub\auth. 
    
    Linux:
    docker run --entrypoint htpasswd registry -Bbn iniyan pass123 > auth/htpasswd
  • Stop the registry container that is already running:
    BAT
    Windows/Linux:
    docker container stop local.hub
    docker container rm local.hub
  • Spin a new container for registry with the following parameters:
    BAT
    Windows:
    docker run -d -p 443:443 --name local.hub -v C:/localhub/certs:/certs 
    -v C:/localhub/registry:/var/lib/registry -v C:/localhub/auth:/auth 
    -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" 
    -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd  -e REGISTRY_HTTP_ADDR=0.0.0.0:443 
    -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/localhub.crt 
    -e REGISTRY_HTTP_TLS_KEY=/certs/localhub.key registry
    
    Linux:
    docker run -d -p 443:443 --name local.hub -v /home/localhub/certs:/certs 
    -v /home/localhub/registry:/var/lib/registry -v /home/localhub/auth:/auth 
    -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" 
    -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd  -e REGISTRY_HTTP_ADDR=0.0.0.0:443 
    -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/localhub.crt 
    -e REGISTRY_HTTP_TLS_KEY=/certs/localhub.key registry
  • Ensure your registry is up and running:
    BAT
    Windows/Linux:
    docker container ls
  • Now, if you try to push/pull a package from the private registry, it will throw an error as connection refused:
    BAT
    Windows/Linux:
     docker pull hub.docker.local/alpine
  • To fix the above error, you need to log in with hub.docker.local:
    BAT
    Windows/Linux:
     docker login hub.docker.local

    Image 4

  • Now, if you try the same command again, it will work like a charm:

    Image 5

  • When you try to access catalog URL https://hub.docker.local/v2/_catalog, it will also prompt you for login:

    Image 6

    Image 7

Conclusion

In this article, we have covered how to secure our private registry with SSL and user authentication. Thanks for reading this article and I hope you find something useful. Please share your valuable comments below. In the next article, I plan to write about "how to register your registry as a service?".

History

  • 17th October, 2018: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)