This article describes how to install Docker Registry on CentOS for personal usage and how to expose it with a self-signed certificate.

Install Docker

yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install docker-ce-18.06.3.ce-3.el7

Commands above install Docker CE 18.06.3. If you need another version, you can check available packages with:
yum list docker-ce.x86_64 --showduplicates | sort -r
The lates version can be installed with:
yum install docker-ce

Generate key/cert pair

Generate a self-signed key/cert pair for the registry

mkdir /root/certs
cd /root/certs
openssl req \
  -newkey rsa:4096 -nodes -sha256 -keyout /root/certs/YOUR_HOSTNAME_HERE.key \
  -x509 -days 365 -out /root/certs/YOUR_HOSTNAME_HERE.crt
Be sure that you used YOUR_HOSTNAME_HERE as CN.

Run and set up the registry

Run Docker Registry with created certificates. Expose it on the host port = 5443

docker run -d \
  --restart=always \
  --name registry \
  -v /root/certs:/certs \
  -v /var/lib/registry:/var/lib/registry \
  -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
  -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/YOUR_HOSTNAME_HERE.crt \
  -e REGISTRY_HTTP_TLS_KEY=/certs/YOUR_HOSTNAME_HERE.key \
  -p 5443:443 \
  registry:2

Instruct every Docker daemon to trust that certificate. In order to do that copy the certificate file (YOUR_HOSTNAME_HERE.crt) to /etc/docker/certs.d/YOUR_HOSTNAME_HERE:5443/ca.crt on every Docker host. You do not need to restart Docker.

mkdir -p /etc/docker/certs.d/YOUR_HOSTNAME_HERE:5443
cp /root/certs/YOUR_HOSTNAME_HERE.crt /etc/docker/certs.d/YOUR_HOSTNAME_HERE:5443/ca.crt

Optionally add your self-signed certificate as a trusted:

cp /root/certs/YOUR_HOSTNAME_HERE.crt /etc/pki/ca-trust/source/anchors/ca.crt
update-ca-trust

Test the registry

Install 'jq' to pretify json output from Docker Registry API:

yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
yum install jq -y

Curl the Registry with GET:
curl https://YOUR_HOSTNAME_HERE:5443/v2/_catalog | jq
The answer will be an empty catalog as we have not loaded any images there.

Empty Docker Registry output

Load an image there and check again if it appears in the Registry.

docker pull busybox
docker tag docker.io/busybox:latest YOUR_HOSTNAME_HERE:5443/busybox:latest
docker push YOUR_HOSTNAME_HERE:5443/busybox:latest
Docker Registry with loaded test image