Build a private docker registry

Motivation

In a previous post I summarized how to start a docker container in user mode.

When using multiple PCs (WorkStation, hereafter WS), it is necessary to consider how to realize a mechanism to share containers among multiple WS. In the case of singularity, we could store sif files on an NFS server and use them from other WS.

In case of docker, I decided to build a registry server, thinking that I could set up a private registry in my home network and operate it.

Sources

I thought it would be easy to build a rootless environment as long as I knew where to store the demon.json file. (xxxx.xxx.xxx.xxx.xxx is the IP address in the private registry’s local network environment)

{
  "insecure-registries':[xxx.xxx.xxx.xxx:5000]"
}

However, it actually took quite a while to resolve the issue. The two pages above were helpful in resolving the issue.

The following is a summary of the steps to build a private registry in a rootless environment and push/pull it from other WSs. For the purpose of explanation, the WS that will be the private registry is called a server, and other WS are called clients.

Configuration

private registry server configuration

Create private key and certificate

Create a directory named “certs” under your $HOME directory, and create a key and a certificate under “certs”.

$ cd
$ mkdir certs
$ openssl req -newkey rsa:2048 -nodes -sha256 -keyout certs/ca.key -x509 -days 3650 -out certs/ca.crt -addext "subjectAltName = IP:192.168.xxx.yyy"

The point in the above is -addext “subjectAltName = IP:192.168.xxx.yyyy”. Here, 192.168.xxx.yyyy is the IP address of the private registry server.

When you execute the above command (openssl), you will be asked to enter the Country Name, etc. Except for the Common Name, you may enter a new line (do not enter anything). For myself, I used the “servername.com”.

/usr/share/ca-certificates/docker

Create a docker directory under /usr/share/ca-certificates and copy the key (ca.key) and certificate (ca.crt) created above.

$ cd
$ sudo mkdir /usr/share/ca-certificates/docker
$ sudo cp certs/ca.* /usr/share/ca-certificates/docker
$ sudo update-ca-certificates
$ sudo vi /etc/ca-certificates.conf

In the last part above, open /etc/ca-certificates.conf with vi and add docker/ca.crt to the last line.

Restart docker daemon

$ systemctl --user restart docker

Start the registry image

$ docker run -d -p 5000:5000 -v $PWD/certs:/certs \
-v /ext/registry:/var/lib/registry \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/ca.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/ca.key \
--restart=always registry:2

To be able to check the contents of the registry from outside the container, “-v /ext/registry:/var/lib/registry” is specified. As shown above, you can add the “-v” option to each mounted item.

Client-side configuration

Key and Certificate Storage

When configuring the client, the key and certificate created on the server side are required. Here, we assume that /mnt/nfs/tmp/ca.* is it.

# cd /usr/share/ca-certificate
# mkdir docker
# cp /mnt/nfs/tmp/ca.* docker
# vi /etc/ca-certificates.conf

Add docker/ca.crt to the last line of /etc/ca-certificates.conf as you did for the server.

# sudo update-ca-certificates

Restart docker daemon

$ systemctl --user restart docker

push image from client side

image to push

On the client side, there is a jupyterlab image like this.

$ docker images
REPOSITORY                  TAG                       IMAGE ID       CREATED         SIZE
pytorch-lab                 latest                    bac68bf54efe   21 hours ago    9.37GB

Tagged with

When pushing to the registry, include the IP address in the registry and tag it as follows

$ docker tag pytorch-lab:latest 192.168.xxx.yyy:5000/pytorch:lab
$ docker images
REPOSITORY                   TAG                      IMAGE ID       CREATED         SIZE
192.168.xxx.yyy:5000/pytorch lab                      bac68bf54efe   21 hours ago    9.37GB
pytorch-lab                  latest                   bac68bf54efe   21 hours ago    9.37GB

push image

$ docker push 192.168.xxx.yyy:5000/pytorch:lab
The push refers to repository [192.168.xxx.yyy:5000/pytorch].
(abbreviated below)

pull image from another client

pull image

$ docker pull 192.168.xxx.yyy:5000/pytorch:lab
lab: Pulling from pytorch
Digest: sha256:807b0cd1b8754072940730a02a1d00933b1c6caedbb162de2b98cbeae642838c
Status: Image is up to date for 192.168.xxx.yyy:5000/pytorch:lab
192.168.xxx.yyy:5000/pytorch:lab

startup

Start the pulled jupyterlab image as follows. In the following example, we assume that the current directory is jupyterlab, which contains the notebook.

$ docker run -d --rm --gpus all -v ${PWD}/jupyterlab:/workdir -p 8888:8888 192.168.xxx.yyy:5000/pytorch:lab

Summary

With the above steps, docker images can now be shared by multiple WSs.

The construction of the docker private registry took a long time and was quite difficult, but I learned a lot about keys, certificates, and other authentication issues through this construction.

I have little experience in this field and may have incorrect information. If you notice any errors, please point them out to me. Thank you in advance.


Translated with www.DeepL.com/Translator (free version)