A Docker registry is a storage and content delivery system that holds named Docker images, available in different tagged versions. Users using Docker interact with a registry by using docker push and docker pull commands. Sometimes it makes sense to store Docker images on a local registry rather than pushing them to Docker hub. In this guide we will setup Private Docker Registry on CentOS 7 secured with Let’s Encrypt SSL Certificate.
You’ll save a lot of bandwidth for a big team and keep the images that you don’t want to be exposed to the public safe. Creating a local docker registry on CentOS 7 is a matter of following few steps. For installation of Docker on different distributions refer to How to install Docker CE on Linux Systems.
Step 1: Install Docker CE on CentOS 7
We’ll use registry 2 Docker image to create a running instance of Docker registry on CentOS 7.
Update your CentOS 7 system:
sudo yum -y update
Run the commands below to install Docker CE on CentOS 7.
sudo curl -o /etc/yum.repos.d/docker-ce.repo https://download.docker.com/linux/centos/docker-ce.repo
Then install Docker CE packages:
sudo yum -y install docker-ce docker-ce-cli containerd.io
If you would like to use Docker as a non-root user, you should now consider adding your user to the “docker” group:
sudo usermod -aG docker $USER newgrp docker
Run the command below to see a version of docker installed.
$ docker --version Docker version 20.10.6, build 370c289
Start and enable docker service:
sudo systemctl enable --now docker
Status should be running:
$ systemctl status docker ● docker.service - Docker Application Container Engine Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled) Active: active (running) since Thu 2021-04-29 19:22:34 UTC; 17s ago Docs: https://docs.docker.com Main PID: 5243 (dockerd) Tasks: 8 Memory: 43.4M CGroup: /system.slice/docker.service └─5243 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
Step 2: Generate Let’s Encrypt SSL Certificates
As promised earlier we’ll use Let’s Encrypt SSL Certificates to secure our Docker Registry setup running on CentOS 7.
certbot tool that will be used to request for Let’s Encrypt certificate.
sudo yum -y install epel-release sudo yum -y install certbot
Request for SSL certificate:
export DOMAIN="registry.domain.com" export EMAIL="[email protected]" certbot certonly --standalone -d $DOMAIN --preferred-challenges http --agree-tos -n -m $EMAIL --keep-until-expiring
Expected certificates generation output:
Saving debug log to /var/log/letsencrypt/letsencrypt.log Plugins selected: Authenticator standalone, Installer None Obtaining a new certificate Performing the following challenges: http-01 challenge for registry.computingforgeeks.com Waiting for verification... Cleaning up challenges IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/registry.computingforgeeks.com/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/registry.computingforgeeks.com/privkey.pem Your cert will expire on 2021-07-28. To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew *all* of your certificates, run "certbot renew" - Your account credentials have been saved in your Certbot configuration directory at /etc/letsencrypt. You should make a secure backup of this folder now. This configuration directory will also contain certificates and private keys obtained by Certbot so making regular backups of this folder is ideal. - If you like Certbot, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le
Your certs will be saved under
- fullchain.pem ⇒ combined file
- chain.pem ⇒ intermediate certificate
- cert.pem ⇒ SSL Server cert(includes public-key)
- privkey.pem ⇒ private-key file
Step 3: Run Docker registry on CentOS 7
You can either run docker registry with SSL or without. We’ll demonstrate how you can run Docker registry with either of the methods.
But first, create a directory that will hold Docker registry images:
sudo mkdir /var/lib/docker/registry
Run Local Docker registry without SSL
$ docker run -d -p 5000:5000 \ --name docker-registry \ --restart=always \ -v /var/lib/docker/registry:/var/lib/registry \ registry:2
Run Local Docker registry with SSL
Create directory and place certs on the host:
export DOMAIN="registry.domain.com" mkdir /certs sudo cp /etc/letsencrypt/live/$DOMAIN/fullchain.pem /certs/fullchain.pem sudo cp /etc/letsencrypt/live/$DOMAIN/privkey.pem /certs/privkey.pem sudo cp /etc/letsencrypt/live/$DOMAIN/cert.pem /certs/cert.pem
Create a Docker Registry container:
docker run -d --name docker-registry --restart=always \ -p 5000:5000 \ -e REGISTRY_HTTP_ADDR=0.0.0.0:5000 \ -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/fullchain.pem \ -e REGISTRY_HTTP_TLS_KEY=/certs/privkey.pem \ -v /certs:/certs \ -v /var/lib/docker/registry:/var/lib/registry \ registry:2
registry.domain.com with your registry subdomain name.
It will download registry:2 docker image if it doesn’t exist and create a container
Unable to find image 'registry:2' locally 2: Pulling from library/registry ddad3d7c1e96: Pull complete 6eda6749503f: Pull complete 363ab70c2143: Pull complete 5b94580856e6: Pull complete 12008541203a: Pull complete Digest: sha256:bac2d7050dc4826516650267fe7dc6627e9e11ad653daca0641437abdf18df27 Status: Downloaded newer image for registry:2 ed960bd27529be26e7ef728027844a62b0731b08bafdbbf63dea328dac46e024
Check container state:
# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ed960bd27529 registry:2 "/entrypoint.sh /etc…" 28 seconds ago Up 27 seconds 0.0.0.0:5000->5000/tcp, :::5000->5000/tcp docker-registry
To push images to Registry Container server, set like below:
$ curl https://$DOMAIN:5000/v2/_catalog "repositories":
If you have SELinux enabled, you may encounter a problem using port 5000, consider disabling SELinux or putting it on permissive mode if you get issues.
If firewalld is enabled and running, allow the port on the firewall.
sudo firewall-cmd --add-port=5000/tcp --permanent sudo firewall-cmd --reload
Step 4: Add Insecure Registry to Docker Engine
By default, docker uses https to connect to docker registry. But there can be use cases to use an insecure registry, especially if you’re on a trusted network. This eliminates the need for a CA-signed certificate for internal use or to trust self-signed certificate in all docker nodes. Here are the steps to add Insecure Registry to Docker Engine.
For Ubuntu Xenial, edit /etc/docker/daemon.json and update the key “insecure-registries”. e.g.
"insecure-registries" : ["registry.domain.com:5000"]
For CentOS 7, edit the file /etc/docker/daemon.json, e.g.
"insecure-registries" : ["registry.domain.com:5000"]
For Ubuntu trusty, edit the file /etc/default/docker and update DOCKER_OPTS, e.g
Then restart Docker engine
sudo systemctl restart docker
Step 5: Pushing Docker images to the local registry
Now that the registry is ready, you can start pushing docker images to it. If you don’t have an active DNS server, use /etc/hosts file to map the hostname to IP Address.
$ sudo vim /etc/hosts 192.168.1.23 registry.domain.com
I’ll download ubuntu latest docker image from Docker hub and push it to my local Docker registry.
$ docker pull ubuntu Using default tag: latest latest: Pulling from library/ubuntu 345e3491a907: Pull complete 57671312ef6f: Pull complete 5e9250ddb7d0: Pull complete Digest: sha256:cf31af331f38d1d7158470e095b132acd126a7180a54f263d386da88eb681d93 Status: Downloaded newer image for ubuntu:latest docker.io/library/ubuntu:latest
Tag the image as registry.domain.com:5000/ubuntu. This creates an additional tag for the existing image. When the first part of the tag is a hostname and port, Docker interprets this as the location of a registry, when pushing.
$ docker tag ubuntu $DOMAIN:5000/ubuntu
Push the image to the local registry running at registry.domain.com:5000/ubuntu
$ docker push $DOMAIN:5000/ubuntu Using default tag: latest The push refers to repository [registry.domain.com:5000/ubuntu] 2f140462f3bc: Pushed 63c99163f472: Pushed ccdbb80308cc: Pushed latest: digest: sha256:86ac87f73641c920fb42cc9612d4fb57b5626b56ea2a19b894d0673fd5b4f2e9 size: 943
If the image upload was successful, you should get sha256 hash at the end. Pushed images are stored under /var/lib/registry/docker/registry/v2/repositories directory.
$ ls /var/lib/docker/registry/docker/registry/v2/repositories/ ubuntu
This is the same method you’ll use to push custom docker images. To download docker images on the local registry, use the command:
$ docker pull registry-hostname:500/image:tag E.g $ docker pull registry.domain.com:5000/ubuntu
On my next guide, I’ll cover configuring nginx proxy for accessing the repository over https.
You can also take a look at Install Docker UI manager – Portainer