While we have learned in a former process how easy it is to upload our own images to the official Docker Hub, everything we put there will be exposed to the public. If you work on a private or closed-source project within a corporate environment or just want to test things out before publishing to everyone, chances are high that you would prefer your own, protected or cooperate-wide private Docker registry. Here in this process we will show you how you can set up and work with your own Docker registry that will be available in your own private network and which will be protected by TLS encryption and which will use user authentication so you can control exactly who can use it (push and pull images to and from it).
To Start With: What Do You Need?
To complete this process, you will require a working installation of the CentOS 7 operating system with root privileges, a console-based text editor of your choice, and a connection to the Internet in order to facilitate the download of additional packages. In our example, we will install the Docker Registry on a server with the IP address 192.168.1.100. Change the proces commands appropriately to fit your needs. You need to have set a FQDN for this server, otherwise, the registry will not work. For simplicity, we will use the /etc/hosts approach instead of setting up and configuring a DNS server (see processes in, Working with Domains if you would like to do this instead). Also, you need an Apache web server on your Docker server running which must be accessible from your whole private network.
The Process
Complete all the following steps in this process with user root on every computer in your network you want to connect to the Docker registry!
- On each computer you want to access your Docker registry, as well as on our Docker registry server itself, with the IP address 192.168.1.100, define the domain name of the Docker registry, which in our example will be dockerserver.home (replace the dockerserver.home part appropriately if you use a different domain name):
echo "export DCKREG=dockerserver.home" >> ~/.bash_profile source ~/.bash_profile
- Now we will define the FQDN of our Docker server registry on each computer in our network we want to use the registry on (as well as on the Docker registry server itself). Log in as root on every machine and type the following command. Skip this step if you have already defined your Docker registry’s server’s domain name via a BIND DNS server (change the IP address of your Docker service 192.168.1.100 appropriately):
echo "192.168.1.100 $DCKREG" >> /etc/hosts
Steps to be done on our Docker registry server (192.168.1.100)
- First create a TLS certificate for our Docker registry certificate (use the FQDN you defined in DCKREG when asked for a Common name (for name; for example your name or your server’s hostname) []:dockerserver.home):
cd; mkdir -p ~/certs; openssl req -newkey rsa:4096 -nodes -sha256
keyout certs/domain.key -x509 -days 365 -out certs/domain.crt - Next, we need to copy the new certificate to the Docker trusted certificate’s location as well as to the system’s default trusted certificate location and rebuild the certificate index:
mkdir -p /etc/docker/certs.d/$DCKREG\:5000
cp ~/certs/domain.crt /etc/docker/certs.d/$DCKREG\:5000/ca.crt
cp ~/certs/domain.crt /etc/pki/ca-trust/source/anchors/docker
registry.crt
update-ca-trust - Also, copy the certificate to our Apache web server so we can easily access it from the Docker clients later:
cp ~/certs/domain.crt /var/www/html/docker-registry.crt
- Next, we will finally download, create, and run our Docker registry as a container:
mkdir ~/auth; touch ~/auth/htpasswd docker run -d -p 5000:5000 - -
restart=always --name registry -v /
root/certs:/certs -v /root/auth:/auth -v /reg:/var/lib/registry -e
REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt -e
REGISTRY_HTTP_TLS_KEY=/certs/domain.key -e
"REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e
REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd -e REGISTRY_AUTH=htpasswd
registry:2 - Now check if the registry is running (in the output you should find it listening on [::]:5000, tls):
docker logs registry
- For setting up user authentication for our registry, use the following command (here we use johndoe as the username and mysecretpassword as the password for authentication. Change these two values to fit your needs. Repeat this command for every user account you want to have later for your users to login):
cd; docker run -it --entrypoint htpasswd -v $PWD/auth:/auth -w /auth registry:2 -Bbc /auth/htpasswd johndoe mysecretpassword
- Next restart the registry to apply your user account changes:
docker restart registry
- Now create a new firewalld service and activate it in our firewall to make incoming connections to our new Docker registry port 5000 possible:
sed 's/80/5000/g' /usr/lib/firewalld/services/http.xml | sed 's/WWW
(HTTP)/Docker registry/g' | sed 's/<description>.*<\/description>//g' >
/etc/firewalld/services/docker-reg.xml
firewall-cmd --reload
firewall-cmd --permanent --add-service=docker-reg; firewall-cmd - -
reload
Steps to be done on every client needing access to our registry
- Finally, we can test connecting to our own new TLS-enhanced private Docker registry with user authentication by logging in on any computer in the same network as our Docker registry with root.
- The first step is to install Docker on every client that wants to connect to the Docker registry:
yum update && curl -sSL https://get.docker.com/ | sh
- Next, on every client wanting to connect to our new Docker registry, set up the server’s certificate on the client first before we are able to connect to it (this step has been tested on CentOS 7 clients only):
mkdir -p /etc/docker/certs.d/$DCKREG\:5000
curl http://$DCKREG/docker-registry.crt -o /tmp/cert.crt
cp /tmp/cert.crt /etc/docker/certs.d/$DCKREG\:5000/ca.crt
cp /tmp/cert.crt /etc/pki/ca-trust/source/anchors/docker-registry.crt
update-ca-trust - For testing, we start by pulling a new small test image from the official Docker Hub. Log in to the official Docker Hub by using your Docker Hub account (see a previous process):
docker login
- Now pull a small image called busybox:
docker pull busybox
- Afterwards, switch the Docker registry server to use our own that we set up in this process (enter the username and password, for example, johndoe / mysecretpassword. Leave the e-mail field blank):
docker login $DCKREG:5000
- Next, to push a Docker image from our client to our new private Docker registry, we need to tag it to be in our registry’s domain:
docker tag busybox $DCKREG:5000/busybox
- Finally, push the image to our own registry:
docker push $DCKREG:5000/busybox
- Congratulations! You have just pushed your first image to your private Docker repository. You can now pull this image $DCKREG:5000/busybox on any other client set up to communicate to our repository. To get a list of all the available images, use (change the account information accordingly):
curl https://johndoe:mysecretpassword@$DCKREG:5000/v2/_catalog
How Does It Work?
In this process, we showed you how to set up your own Docker registry running in a Docker container on the server. It is very important to understand that you will need to configure a FQDN for your registry server because it is mandatory for the whole system to work.
So what did we learn from this experience?
We began by configuring the Docker registry’s FQDN on every computer using the /etc/hosts approach. Then we created a new certificate on the Docker registry server which will be used to communicate securely using TLS encryption between clients and registry. Next we installed the new generated certificate on the httpd server, so it is accessible to all the clients later; also in a specific Docker directory to make it accessible for Docker as well; and in the default trusted certificate location of the server where we also rebuilt the certificate cache for this server. Afterwards, we used the docker run command to download, install, and run our new Docker registry in a docker container itself on this server. We provided a list of parameters to configure TLS encryption and user authentication.
In the next step, we attached to the registry to create new htpasswd accounts. You can repeat this step whenever you need new accounts for your registry. Don’t forget to restart the registry container afterwards. Next, on every client we want to make communications to our new Docker registry, we need to install the server’s certificate also in the same places as on the server itself; thus we downloaded it from the HTTP source implemented previously and copied it to the various locations. To test things out on the client, next we connected to the official Docker Hub to download a random image we wanted to push to our own registry in the next step. We downloaded the busybox image to our own image cache and afterwards switched to connecting to our new private Docker registry. Before we could upload the image to the new location, we had to give it a proper tag that fitted the new server name and then we were able to push the image to our new Docker registry. The server is now available at port 5000 in the complete network. Remember that, if you don’t want to use your own registry any more on the clients, you can always switch back to the official docker repository using docker login.
There is so much more to learn about Docker. In the processes of this segment, we only scratched the surface of the Docker platform. If you want to learn more about it, consider going to https://www.Packtpub.com and check out one of the many titles available at this website about it.