Docker registry en una red local

Un poco de Docker…

En docker existen imágenes y contenedores. De manera sencilla, un contenedor es un proceso en ejecución de una imagen docker. En Docker podemos hacer commits de nuestros contenedores, lo que nos permite crear imágenes que contienen cambios en configuraciones, rutas, nombres de archivos, etc. Las imágenes muchas veces necesitan ser subidas a un repositorio para después poder ser descargadas por otros clientes, en docker un registry es un repositorio de imágenes y es lo que hoy vamos a instalar y probar.

El tener un registry privado de docker resulta útil cuando intentamos implementar procesos de Continuous Integration, Continuous Delivery o Continuous Deployment en nuestra organización.

Para nuestro post vamos a ejecutar un contenedor de la imagen registry y a crear los certificados que nos permitan accederlo en nuestra red local. Vamos a suponer que nuestro registry estará en la IP 10.10.1.37 y nuestro cliente es el 10.10.1.110.

Descargar y configurar la imagen

Según la documentación oficial de docker, el puerto por defecto para el registro es el 5000, vamos a seguir usando el mismo por lo que en algunos pasos lo omitiremos de los comandos.

$ docker run -d -p 5000:5000 --restart=always --name registry \ 
-v /mnt/registry:/var/lib/registry registry:2

De esta forma tendremos un contenedor que puede ser accedido solo de manera local, esto para fines didácticos está bien, pero es inútil para una aplicación real; un registry tiene que poder enviar/recibir imágenes de clientes al menos en su red local. Si ejecutaste el comando anterior puedes detener la imagen y borrarla con los siguientes comandos:

$ docker stop registry && docker rm registry

Certificados en el servidor

Vamos a crear los certificados necesarios para ello. Necesitas tener instalado openssl y editar el archivo

/etc/ssl/openssl.cnf

Agregamos una regla en la sección [ v3_ca ] Para tener algo como lo siguiente:

[ v3_ca ]
subjectAltName = IP:10.10.1.37

Vamos a crear una carpeta en nuestro home llamada certs, después de ello creamos nuestras llaves:

$ openssl req  -newkey rsa:4096 -nodes -sha256 -keyout ~/certs/domain.key  -x509 -days 1365 -out ~/certs/domain.crt

Generating a RSA private key
………………..++++
……………………………………………………………………………….++++
writing new private key to ‘domain.key’

You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter ‘.’, the field will be left blank.

Country Name (2 letter code) [AU]:MX
State or Province Name (full name) [Some-State]:Estado-Mexico
Locality Name (eg, city) []:Toluca
Organization Name (eg, company) [Internet Widgits Pty Ltd]:CodigoChido
Organizational Unit Name (eg, section) []:posts
Common Name (e.g. server FQDN or YOUR name) []:10.10.1.37
Email Address []:paklei@codigochido.com

En el paso anterior Ahora vamos a ejecutar un contenedor con los certificados que creamos:

    $ docker run -d \                   
  --restart=always \
  --name registry \
  -v ~/certs:/certs \
  -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
  -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
  -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
  -e REGISTRY_STORAGE_DELETE_ENABLED=true \
  -p 443:443 \
  registry:2

Podemos mirar el contenido de nuestro registry a través de la siguiente URL: https://10.10.1.37/v2/_catalog

Certificados en los clientes

Si intentamos conectarnos al registry desde un cliente, tendremos una salida como la siguiente:

[paklei@CentOS ~]$ docker login 10.10.1.37
Username: a
Password:
Error response from daemon: Get https://10.10.1.37/v2/: x509: certificate signed by unknown authority

Vamos a configurar nuestro cliente para que confíe en el certificado self-signed que generamos previamente en el servidor. En cada uno de los clientes que se conectarán al registry necesitamos copiar el certificado generado en nuestro host (el archivo domain.crt que se encuentra en la carpeta certs que creamos previamente), para ello necesitamos crear el siguiente archivo:

/etc/docker/certs.d/10.10.1.37/ca.crt

-----BEGIN CERTIFICATE-----
muchasLetras
HolaMundo!!
MuchosNúmeros
OtroTantoMásDeLetras
....PuntosSuspensivosPorQueNo?
-----END CERTIFICATE-----

Con lo anterior podemos conectarnos a nuestro registry

[paklei@CentOS ~]$ docker login 10.10.1.37
Authenticating with existing credentials… WARNING! Your password will be stored unencrypted in /paklei/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

Ahora vamos a probar que podamos hacer un push y pull desde nuestro cliente. Vamos a descargar la imagen de alpine:latest, crear un tag con la nomenclatura necesaria y el push.

[paklei@CentOS ~]$ docker pull alpine:latest
latest: Pulling from library/alpine
ca784148e348: Pull complete
Digest: sha256:46e71df1e5191ab8b803rrre325258ec44ea739bba1e5645cff83c9048ff1
Status: Downloaded newer image for alpine:latest
[paklei@CentOS ~]$ docker tag alpine:latest 10.10.1.37/alpine-test-push
[paklei@CentOS ~]$ docker push 10.10.1.37/alpine-test-push
The push refers to repository [10.10.1.37/alpine-test-push]
7tff100f35cb: Pushed
latest:digest:sha256:4d2e482b82608d1y3a374df3357c0291589a61cc194ec4a9ca2381073a17f58e size: 528

Para consultar que nuestro registry tenga la imagen podemos ejecutar en GET en nuestro navegador y agregar la excepción del certificado self-signed, deberíamos mirar un response como el siguiente:

 https://10.10.1.37/v2/_catalog  
 {"repositories":["alpine-test-push"]}

Ahora sabemos que nuestro registry puede recibir las imágenes que le sean enviadas por el cliente 10.10.1.100, vamos a comprobar que nuestro cliente puede hacer pull sin problemas de nuestro registry, para ello vamos a borrar las imágenes de alpine y alpine-test-push y después intentaremos hacer el pull del registry.

[paklei@CentOS ~]$ docker image remove alpine:latest
Untagged: alpine:latest
Untagged: alpine@sha256:abc
[paklei@CentOS ~]$ docker image remove 10.10.1.37/alpine-test-push:latest
Untagged: 10.10.1.37/alpine-test-push:latest
Untagged: 10.10.1.37/alpine-test-push@sha256:abc
Deleted: sha256:abc
Deleted: sha256:abc
[paklei@CentOS ~]$ docker pull 10.10.1.37/alpine-test-push
Using default tag: latest
latest: Pulling from alpine-test-push
cd784348: Pull complete Digest: sha256:abc
Status: Downloaded newer image for 10.10.1.37/alpine-test-push:latest
[paklei@CentOS ~]$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
10.10.1.37/alpine-test-push latest 3f5f94 2 days ago 4.41MB

De esta forma tenemos un registry que puede aceptar cualquier push/pull de un cliente que cuente con el certificado correcto.

Esperamos que les sea útil. Saludos.

comments powered by Disqus