Como Configurar un Registro Privado de Docker en Linux

Advertencia
Este artículo se actualizó por última vez el 2022-04-19, el contenido puede estar desactualizado.

Antes de comenzar, quería contarles que hay una promoción en DigitalOcean donde te dan un crédito de USD 100.00 durante 60 días para que puedas probar los servicios que este Proveedor Cloud ofrece. Lo único que tienes que hacer es suscribirte a DigitalOcean con el siguiente botón:

DigitalOcean Referral Badge

O a través del siguiente enlace: https://bit.ly/digitalocean-itsm


Si estás ejecutando microservicios en Docker en tu propia infraestructura, puede que estés interesado en tener tu propio repositorio privado de imágenes Docker. Puede ser por razones de seguridad o para que tus despliegues on-premises sean más rápidos. En este articulo te enseñaré como configurar un registro privado de Docker en Linux.

Esta guía asume que ya tienes instalado Docker en el host. Si aún no lo haz hecho, te puedo referir a nuestro articulo: Como Instalar Docker en Linux

Vamos a utilizar Let’s Encrypt para generar los certificados para el Registro. Asumo también que ya tienes configurado el dominio y que permita la conexión con los puertos 80 (https) y 443 (https)


El certificado vencerá cada 90 días y es gratuito renovarlo, sin embargo, certbot nos hará el trabajo de hacerlo por nosotros.

Instalamos la herramienta certbot que nos permitirá solicitar el certificado:

  • Ubuntu 22.04, 20.04, 18.04
1
2
sudo apt update
sudo apt install certbot -y
  • Rocky Linux / Alma Linux / RHEL 8
1
2
sudo dnf update
sudo dnf install certbot -y

Solicitamos el certificado: yes

1
2
3
export DOMAIN="registry.domain.com"
export EMAIL="email@domain.com"
certbot certonly --standalone -d $DOMAIN --preferred-challenges http --agree-tos -n -m $EMAIL --keep-until-expiring

Donde:

  • DOMAIN: colocamos nuestro dominio.
  • EMAIL: colocamos un email del contacto administrativo.

La salida esperada sería más o menos así:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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

Los certificados se almacenará en el directorio /etc/letsencrypt/live/

1
2
/etc/letsencrypt/live/registry.domain.com/fullchain.pem
/etc/letsencrypt/live/registry.domain.com/privkey.pem

Donde:

  • fullchain.pem ⇒ archivo resultante de la combinación de cert.pem y chain.pem.
  • chain.pem ⇒ certificado intermediario.
  • cert.pem ⇒ certificado SSL Server(incluye la clave pública)
  • privkey.pem ⇒ la llave privada.

Podemos configurar nuestro registro con o sin SSL.

Creamos el directorio donde se va a almacenar las imágenes del registro:

1
sudo mkdir /var/lib/docker/registry

Para ejecutar el Registro Local sin SSL:

1
2
3
4
5
docker run -d -p 5000:5000 \
  --name docker-registry \
  --restart=always \
  -v /var/lib/docker/registry:/var/lib/registry \
  registry:2

Para ejecutar el Registro Local con SSL:

Creamos un directorio donde copiaremos los certificados SSL, en este caso en el directorio /certs:

1
2
3
4
5
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
Consejo
Recuerda cambiar domain.com por tu dominio.

Creamos entonces el contenedor con el Registro, la cual descargará desde DockerHub en caso de no tenerla ya:

1
2
3
4
5
6
7
8
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

Validamos que el contenedor esté ejecutandose:

1
docker ps

Para hacer push de imagenes al Registro:

1
curl https://$DOMAIN:5000/v2/_catalog

Descargamos dos imágenes desde DockerHub para subirlas a nuestro repositorio local:

1
2
docker pull alpine
docker pull ubuntu

Etiquetamos ambas imágenes:

1
2
docker tag ubuntu $DOMAIN:5000/ubuntu:v1
docker tag alpine $DOMAIN:5000/alpine:v1

Subimos las imágenes:

1
2
docker push $DOMAIN:5000/alpine:v1
docker push $DOMAIN:5000/ubuntu:v1

Hagamos una prueba desde otra máquina en la misma red del repositorio local:

1
docker pull registry.domain.com:5000/ubuntu:v1

Y si ejecutamos el comando docker images deberíamos ver la imagen de Ubuntu descargada y con la dirección del Repositorio.


Los Registros deben tener implementados mecanismos para que solo usuarios autorizados puedan acceder a el (a menos que ese registro sea público, que no es nuestro caso) La manera más simple de lograr esto es restringiendo el acceso con autenticación básica:

Crea un archivo con una sola linea (la contraseña) para el usuario dockadmin, con la contraseña password:

1
2
3
docker run \
--entrypoint htpasswd \
registry:2 -Bbn dockadmin registrypassword > ~/.htpasswd

Eliminamos el contenedor:

1
docker rm -f docker-registry

Y ahora lo levantamos de nuevo con la autenticación:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
docker run -d --name docker-registry --restart=always \
-p 5000:5000 \
-v ~/.htpasswd:/auth_htpasswd \
-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: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

Si intentamos descargar una imagen, lo mas probable es que nos muestre este mensaje de error:

1
Error response from daemon: Get https://registry.domain.com:5000/v2/ubuntu/manifests/v1: no basic auth credentials

Lo cual quiere decir que la autenticación está funcionando y por ende debemos iniciar sesión:

1
2
3
4
5
6
7
8
docker login registry.domain.com:5000
Username: dockadmin
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

Por lo que ya seriamos capaces de bajar y de subir imágenes a nuestro Registro Privado.

Espero les haya gustado y nos vemos en la próxima! Happy Dockering 😄


Si te pareció útil este artículo y el proyecto en general, considera brindarme un café :)

Buy me a coffeeBuy me a coffee