Desplegando un registro de Docker privado y seguro

En nuestro último articulo os mostramos como generar una imagen de docker. Si quieres compartir esta imagen con tu equipo, existe la posibilidad de exportarla a un archivo tar, o se puede usar el archivo Dockerfile para construir de nuevo la imagen en cada uno de los docker host donde va a ser utilizada. Tener que reconstruir la imagen en el pc de cada uno de los componentes de tu equipo no es algo práctico. ¿No sería mejor si pudiéramos descargar imágenes ya listas para usar? Para resolver este problema disponemos de un elemento que docker denomina registro, donde podemos subir y bajar nuestras imágenes.

El proyecto Docker dispone de un registro público https://registry.hub.docker.com/. Sin embargo es probable que tus imágenes no sean públicas y necesites un registro privado para almacenarlas. Incluso si tus imagenes pueden almacenarse en el registro público de Docker, puede resultarte interesante tener un registro privado en tu empresa con las mismas imágenes, para ser usado en el flujo de integración continua que tengáis en vuestra empresa/proyecto.

img_4

En este articulo vamos a enseñaros como montar un registro de docker (version 0.9.1) para almacenar vuestras imágenes privadas. Aunque Docker publicó recientemente la versión 2.0 de su registro, creemos que aún no esta madura para usarla en producción ya que echamos de menos ciertas funcionalidades que si tenemos disponibles en la versión 0.9.1.

Por defecto el registro se levanta sobre una conexión HTTP en claro y sin autenticación. Lo que vamos a ver a continuación es como securizarlo mediante el uso de TLS y autenticación HTTP básica.

Componentes requeridos

  • Imagen de docker nginx version 1.7
  • Imagen de docker registry version 0.9.1
  • Imagen de docker docker-registry-frontend version latest
  • Un certificado SSL valido asociado al nombre de dominio público(FQDN) qie vamos a usar para acceder al registro. En el ejemplo vamos a usar register.example.com

Docker Registry (1)

1. Vamos a usar diferentes contenedores para desplegar nuestro registro, por lo que necesitamos un docker host donde desplegarlos.

2. Arrancamos un contenedor docker usando la imagen «registry» version 0.9.1

docker run -t -d -v /opt/registry-v1:/tmp/registry-dev --name docker-registry-v1 registry:0.9.1
  • Con este comando arrancamos un nuevo contenedor de Registro llamado «docker-registry-v1» con version 0.9.1  (descargado del registro público).
  • El nombre asignado a este container es importante porque lo usaremos más adelante.
  • Necesitaras una cuenta de usuario en el registro público para poder descargar imagenes.
  • Con la opción «-v /opt/registry-v1:/tmp/registry-dev» mapeamos un directorio del docker host donde el registro de docker irá colocando todos sus archivos. De este modo si paramos este container y arrancamos uno nuevo, por ejemplo para subir de versión, podremos reusar el árbol de directorios para no tener que subir de nuevo las imágenes.

Note: el registro escucha normalmente en el puerto 5000 pero por motivos de seguridad no vamos a mapearlo al exterior

3. Arrancamos un contenedor con la imagen nginx versión +1.7 para montar un proxy inverso

  • El objetivo es tener un proxy inverso apuntando a nuestro registro y que además gestionara la conexión TLS y la autenticación HHTP básica. Como requerimiento, necesitamos un fichero donde almacenar los usuarios y credenciales que vamos a usar, y el certificado SSL y la clave pública correspondiente, expedidas por una entidad certificadora reconocida (CA)

Note: El demonio de docker considera que un registro privado es seguro solo si usa TLS en su conexión y el docker host es capaz de reconocer la validez del certificado. Si usáis certificados autofirmados, o tenéis una CA interna de la empresa será necesario que el demonio de docker arranque con la opción –insecure-registry

docker run -t -d -p 443:443 -e REGISTRY_HOST="docker-registry-v1" \
-e REGISTRY_PORT="5000" \
-e SERVER_NAME="register.example.com" \
--link docker-registry-v1:docker-registry-v1 \
-v /opt/.htpasswd:/etc/nginx/.htpasswd:ro \
-v /opt/certs:/etc/nginx/ssl:ro \
jmaciasportela/docker-registry-proxy-v1
  • Mapeamos el puerto externo(internet) 443 con el interno 443.
  • La variable de entorno REGISTRY_HOST es el nombre que asignamos al contenedor en el punto 2.
  • La variable de entorno REGISTRY_PORT es el puerto en el que el registro está escuchando.
  • La variable de entorno SERVER_NAME es la dirección publica del registro privado. IMPORTANTE: Tiene que coincidir con el FQDN del certificado SSL.
  • Enlazamos este contenedor con el que creamos en el punto 2 usando el nombre ‘docker-registry-v1’, habilitando al proxy nginx a conectar con el registro sin conocer su ip, usando solo el nombre.
  • Mapeamos (en modo solo lectura) el fichero htpasswd, con las credenciales para conectar con el registro. Podéis crear uno fácilmente con el comando:
htpasswd -c htpasswd user_XXX
  • Mapeamos (en modo solo lectura) el directorio donde tenemos los certificados, que han de llamarse docker-registry.crt y docker-registry.key, con el directorio interno que usa nginx para buscar los certificados.

4. En este punto ya tenemos disponible nuestro registro. Para empezar a usarlo necesitamos logearnos.

docker login register.example.com

Username: jmacias
Password: *****
Email: 
Login Succeeded

5. Imaginemos que tenemos el proyecto Docker del anterior articulo con el «Hello World»

docker build -t "register.example.com/hello" .
docker push register.example.com/hello

6. Desde cualquier otro docker host de tu organización

docker login register.example.com
docker pull register.example.com/hello
docker run -d hello

7. Como punto extra vamos a desplegar un frontend para nuestro registro.

docker run -d -e ENV_DOCKER_REGISTRY_HOST=docker-registry-v1 \
-e ENV_DOCKER_REGISTRY_PORT=5000 \
-e ENV_REGISTRY_PROXY_FQDN=register.example.com \
-e ENV_REGISTRY_PROXY_PORT=443 \
--link docker-registry-v1:docker-registry-v1 \
-e ENV_USE_SSL=yes \
-v /opt/certs/docker-registry.crt:/etc/apache2/server.crt:ro \
-v /opt/certs/docker-registry.key:/etc/apache2/server.key:ro \
-p 8443:443 \  
konradkleine/docker-registry-frontend
  • La variable de entorno ENV_DOCKER_REGISTRY_HOST es el nombre que asignamos al contenedor en el punto 2
  • La variable de entorno ENV_DOCKER_REGISTRY_PORT es el puerto en el que el registro está escuchando.
  • La variable de entorno ENV_REGISTRY_PROXY_FQDN es la dirección publica del registro privado.
  • La variable de entorno ENV_REGISTRY_PROXY_PORT es el puerto en el que el proxy inverso nginx está escuchando.
  • Enlazamos este contenedor con el que creamos en el punto 2 usando el nombre ‘docker-registry-v1’, habilitando al proxy nginx a conectar con el registro sin conocer su ip, usando solo el nombre.
  • La variable de entorno ENV_USE_SSL para forzar el uso de SSL. En este ejemplo usamos los mismos certificados que usamos en el punto 3, pero ahora docker-registry.crt se mapea con server.crt y docker-registry.key se mapea con server.key
  • Mapeamos el puerto externo 8443 con el interno 443, de modo que podríamos acceder desde internet https://register.example.com:8443

img_1

Note: El frontend nos permite gestionar nuestro registo de una manera sencilla y visual

8. Un extra de seguridad

  • Al arrancar el fronted puedes añadir una variable de entorno nueva para que arranque en modo solo lectura: -e ENV_MODE_BROWSE_ONLY=true
  • Podemos añadir autenticación básica al frontend.

Sobre el contenedor de frontend arrancado, buscamos su dockerid y:

docker exec -t -i DOCKERID bash -l

root@e259f5121968:/# apt-get update
root@e259f5121968:/# apt-get install apache2-utils vim
root@e259f5121968:/# htpasswd -c /etc/apache2/users USERXX
root@e259f5121968:/# vim /etc/apache2/sites-enabled/docker-site.conf

Añadimos estas lineas dentro del tag  <Directory /var/www/html> tag:

    AuthType Basic
    AuthName "ownCloud docker Registry"
    AuthUserFile /etc/apache2/users
    Require valid-user

Recargamos el servicio de apache y salimos del container

root@e259f5121968:/# service apache2 reload
root@e259f5121968:/# exit

Si habéis llegado hasta aquí, es probable que os haya gustado el articulo, así que animaros a dejar algún comentario!

REFERENCIAS

Docker – Entregando Software
Docker II – Construyendo un contenedor
Docker Registry 2.0: http://container-solutions.com/2015/04/running-secured-docker-registry-2-0/
Docker Registry Frontend: https://github.com/kwk/docker-registry-frontend
Docker cheat sheet: https://github.com/wsargent/docker-cheat-sheet#registry–repository

Deja un comentario

¿Necesitas una estimación?

Calcula ahora

Centro de preferencias de privacidad

Cookies propias

__unam, gdpr 1P_JAR, DV, NID, _icl_current_language

Cookies de analítica

Estas cookies nos ayudan a comprender cómo los usuarios interactúan con nuestra página web.

_ga, _gat_UA-42883984-1, _gid, _hjIncludedInSample,

Cookies de suscripción

Estas cookies se utilizan para ejecutar funciones de la Web, como no mostrar el banner publicitario y / o recordar la configuración del usuario dentro de la sesión.

tl_3832_3832_2 tl_5886_5886_12 tve_leads_unique

Otra