Cómo configurar un registro Docker privado en Ubuntu 20.04

Índice
  1. Introducción
  • Prerrequisitos
  • Paso 1: Instalación y configuración del registro de Docker
  • Paso 2: Configuración del reenvío de puertos de Nginx
  • Paso 3: Configuración de la autenticación
  • Paso 4: iniciar Docker Registry como servicio
  • Paso 5: Aumentar el tamaño de carga de archivos para Nginx
  • Paso 6: Publicación en su registro privado de Docker
  • Paso 7: extracción desde su registro privado de Docker
  • Conclusión
  • El autor seleccionó el Fondo de Código Libre y Abierto para recibir una donación como parte del programa Write for DOnations .

    Introducción

    Docker Registry es una aplicación que administra el almacenamiento y la entrega de imágenes de contenedores Docker. Los registros centralizan las imágenes de contenedores y reducen los tiempos de compilación para los desarrolladores. Las imágenes de Docker garantizan el mismo entorno de ejecución a través de la virtualización, pero la compilación de una imagen puede implicar una inversión de tiempo significativa. Por ejemplo, en lugar de instalar dependencias y paquetes por separado para usar Docker, los desarrolladores pueden descargar una imagen comprimida de un registro que contiene todos los componentes necesarios. Además, los desarrolladores pueden automatizar el envío de imágenes a un registro mediante herramientas de integración continua, como TravisCI , para actualizar las imágenes sin problemas durante la producción y el desarrollo.

    Docker también cuenta con un registro público gratuito, Docker Hub , que puede alojar sus imágenes de Docker personalizadas, pero existen situaciones en las que no querrá que su imagen esté disponible públicamente. Las imágenes suelen contener todo el código necesario para ejecutar una aplicación, por lo que es preferible utilizar un registro privado cuando se utiliza software propietario.

    En este tutorial, configurará y protegerá su propio registro privado de Docker. Utilizará Docker Compose para definir configuraciones para ejecutar sus contenedores de Docker y Nginx para reenviar el tráfico del servidor desde Internet al contenedor de Docker en ejecución. Una vez que haya completado este tutorial, podrá enviar una imagen de Docker personalizada a su registro privado y extraer la imagen de forma segura desde un servidor remoto.

    Prerrequisitos

    • Dos servidores Ubuntu 20.04 configurados siguiendo la Guía de configuración inicial del servidor Ubuntu 20.04 , incluido un sudousuario no root y un firewall. Un servidor alojará su registro Docker privado y el otro será su servidor cliente .
    • Docker se instaló en ambos servidores siguiendo los pasos 1 y 2 de Cómo instalar y usar Docker en Ubuntu 20.04 .
    • Docker Compose instalado en el servidor host siguiendo el Paso 1 de Cómo instalar y usar Docker Compose en Ubuntu 20.04 .
    • Nginx instalado en su servidor host siguiendo los pasos en Cómo instalar Nginx en Ubuntu 20.04 .
    • Nginx protegido con Let’s Encrypt en su servidor para el registro privado de Docker, siguiendo el tutorial Cómo proteger Nginx con Let’s Encrypt en Ubuntu 20.04 . Asegúrese de redirigir todo el tráfico de HTTP a HTTPS en el paso 4 .
    • Un nombre de dominio que se resuelve en el servidor que estás usando para el registro privado de Docker. Lo configurarás como parte del requisito previo de Let’s Encrypt. En este tutorial, lo llamaremos your_domain.

    Paso 1: Instalación y configuración del registro de Docker

    Docker en la línea de comandos es útil al comenzar y probar contenedores, pero resulta difícil de manejar para implementaciones más grandes que involucran múltiples contenedores ejecutándose en paralelo.

    Con Docker Compose, puedes escribir un .ymlarchivo para configurar cada contenedor y la información que estos necesitan para comunicarse entre sí. Puedes usar la docker-composeherramienta de línea de comandos para enviar comandos a todos los componentes que conforman tu aplicación y controlarlos como un grupo.

    Docker Registry es en sí mismo una aplicación con varios componentes, por lo que utilizará Docker Compose para administrarlo. Para iniciar una instancia del registro, configurará un docker-compose.ymlarchivo para definirlo y la ubicación en el disco donde el registro almacenará sus datos.

    Almacenarás la configuración en un directorio llamado docker-registryen el servidor principal. Créalo ejecutando:

    1. mkdir ~/docker-registry

    Navega hasta él:

    1. cd ~/docker-registry

    Luego, crea un subdirectorio llamado data, donde tu registro almacenará sus imágenes:

    1. mkdir data

    Cree y abra un archivo llamado docker-compose.ymlejecutando:

    1. nano docker-compose.yml

    Agregue las siguientes líneas, que definen una instancia básica de un Registro Docker:

    ~/docker-registry/docker-compose.yml

    version: '3'services:  registry:    image: registry:2    ports:    - "5000:5000"    environment:      REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data    volumes:      - ./data:/data

    Primero, se le asigna un nombre al primer servicio registryy se establece su imagen en registry, version 2. Luego, en ports, se asigna el puerto 5000en el host al puerto 5000del contenedor. Esto le permite enviar una solicitud al puerto 5000en el servidor y hacer que la solicitud se reenvíe al registro.

    En la environmentsección, se establece la REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORYvariable en /data, especificando en qué volumen debe almacenar sus datos. Luego, en la volumessección, se asigna el /datadirectorio en el sistema de archivos del host a /dataen el contenedor, que actúa como un paso a través. Los datos se almacenarán en realidad en el sistema de archivos del host.

    Guarde y cierre el archivo.

    Ahora puede iniciar la configuración ejecutando:

    1. docker-compose up

    Se descargarán e iniciarán el contenedor de registro y sus dependencias.

    OutputCreating network "docker-registry_default" with the default driverPulling registry (registry:2)...2: Pulling from library/registrye95f33c60a64: Pull complete4d7f2300f040: Pull complete35a7b7da3905: Pull completed656466e1fe8: Pull completeb6cb731e4f93: Pull completeDigest: sha256:da946ca03fca0aade04a73aa94b54ff0dc614216bdd1d47585f97b4c1bdaa0e2Status: Downloaded newer image for registry:2Creating docker-registry_registry_1 ... doneAttaching to docker-registry_registry_1registry_1  | time="2021-03-18T12:32:59.587157744Z" level=warning msg="No HTTP secret provided - generated random secret. This may cause problems with uploads if multiple registries are behind a load-balancer. To provide a shared secret, fill in http.secret in the configuration file or set the REGISTRY_HTTP_SECRET environment variable." go.version=go1.11.2 instance.id=119fe50b-2bb6-4a8d-902d-dfa2db63fc2f service=registry version=v2.7.1registry_1  | time="2021-03-18T12:32:59.587912733Z" level=info msg="redis not configured" go.version=go1.11.2 instance.id=119fe50b-2bb6-4a8d-902d-dfa2db63fc2f service=registry version=v2.7.1registry_1  | time="2021-03-18T12:32:59.598496488Z" level=info msg="using inmemory blob descriptor cache" go.version=go1.11.2 instance.id=119fe50b-2bb6-4a8d-902d-dfa2db63fc2f service=registry version=v2.7.1registry_1  | time="2021-03-18T12:32:59.601503005Z" level=info msg="listening on [::]:5000" go.version=go1.11.2 instance.id=119fe50b-2bb6-4a8d-902d-dfa2db63fc2f service=registry version=v2.7.1...

    No HTTP secret providedMás adelante en este tutorial abordarás el mensaje de advertencia. Observa que la última línea de la salida muestra que ha comenzado a escuchar correctamente en el puerto 5000.

    Puedes presionar CTRL+Cpara detener su ejecución.

    En este paso, ha creado una configuración de Docker Compose que inicia un Docker Registry que escucha en el puerto 5000. En los siguientes pasos, lo expondrá en su dominio y configurará la autenticación.

    Paso 2: Configuración del reenvío de puertos de Nginx

    Como parte de los requisitos previos, habilitó HTTPS en su dominio. Para exponer su registro de Docker seguro allí, solo necesitará configurar Nginx para reenviar el tráfico desde su dominio al contenedor de registro.

    Ya ha configurado el archivo que contiene la configuración de su servidor. Ábralo para editarlo ejecutando:/etc/nginx/sites-available/your_domain

    1. sudo nano /etc/nginx/sites-available/your_domain

    Encuentra el locationbloque existente:

    /etc/nginx/sites-available/su_dominio

    ...location / {  ...}...

    Debe reenviar el tráfico al puerto 5000, donde su registro escuchará el tráfico. También desea agregar encabezados a la solicitud reenviada al registro, lo que proporciona información adicional del servidor sobre la solicitud en sí. Reemplace el contenido existente del locationbloque con las siguientes líneas:

    /etc/nginx/sites-available/su_dominio

    ...location / {    # Do not allow connections from docker 1.5 and earlier    # docker pre-1.6.0 did not properly set the user agent on ping, catch "Go *" user agents    if ($http_user_agent ~ "^(docker/1.(3|4|5(?!.[0-9]-dev))|Go ).*$" ) {      return 404;    }    proxy_pass                          http://localhost:5000;    proxy_set_header  Host              $http_host;   # required for docker client's sake    proxy_set_header  X-Real-IP         $remote_addr; # pass on real client's IP    proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;    proxy_set_header  X-Forwarded-Proto $scheme;    proxy_read_timeout                  900;}...

    El ifbloque comprueba el agente de usuario de la solicitud y verifica que la versión del cliente Docker sea superior a 1.5, así como que no se trate de una Goaplicación que esté intentando acceder. Para obtener más información sobre esto, puede encontrar la nginxconfiguración del encabezado en la guía de Nginx del registro de Docker .

    Guarde y cierre el archivo cuando haya terminado. Aplique los cambios reiniciando Nginx:

    1. sudo systemctl restart nginx

    Si recibe un error, vuelva a verificar la configuración que ha agregado.

    Para confirmar que Nginx está reenviando correctamente el tráfico a su contenedor de registro en el puerto 5000, ejecútelo:

    1. docker-compose up

    Luego, en una ventana del navegador, navegue hasta su dominio y acceda al v2punto final, de la siguiente manera:

    https://your_domain/v2

    Verás un objeto JSON vacío:

    {}

    En tu terminal recibirás un resultado similar al siguiente:

    Outputregistry_1  | time="2018-11-07T17:57:42Z" level=info msg="response completed" go.version=go1.7.6 http.request.host=cornellappdev.com http.request.id=a8f5984e-15e3-4946-9c40-d71f8557652f http.request.method=GET http.request.remoteaddr=128.84.125.58 http.request.uri="/v2/" http.request.useragent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/604.4.7 (KHTML, like Gecko) Version/11.0.2 Safari/604.4.7" http.response.contenttype="application/json; charset=utf-8" http.response.duration=2.125995ms http.response.status=200 http.response.written=2 instance.id=3093e5ab-5715-42bc-808e-73f310848860 version=v2.6.2registry_1  | 172.18.0.1 - - [07/Nov/2018:17:57:42 +0000] "GET /v2/ HTTP/1.0" 200 2 "" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/604.4.7 (KHTML, like Gecko) Version/11.0.2 Safari/604.4.7"

    En la última línea, puede ver que GETse realizó una solicitud a /v2/, que es el punto final al que envió una solicitud, desde su navegador. El contenedor recibió la solicitud que realizó, desde el reenvío de puertos, y devolvió una respuesta de {}. El código 200en la última línea de la salida significa que el contenedor gestionó la solicitud correctamente.

    Presione CTRL+Cpara detener su ejecución.

    Ahora que ha configurado el reenvío de puertos, pasará a mejorar la seguridad de su registro.

    Paso 3: Configuración de la autenticación

    Nginx te permite configurar la autenticación HTTP para los sitios que administra, lo que puedes usar para limitar el acceso a tu Registro Docker. Para lograrlo, crearás un archivo de autenticación htpasswdy le agregarás combinaciones de nombre de usuario y contraseña que serán aceptadas.

    Puede obtener la htpasswdutilidad instalando el apache2-utilspaquete. Para ello, ejecute:

    1. sudo apt install apache2-utils -y

    Almacenarás el archivo de autenticación con las credenciales en ~/docker-registry/auth. Créalo ejecutando:

    1. mkdir ~/docker-registry/auth

    Navega hasta él:

    1. cd ~/docker-registry/auth

    Crea el primer usuario, reemplázalo usernamecon el nombre de usuario que quieras utilizar. La -Bbandera ordena el uso del bcryptalgoritmo que Docker requiere:

    1. htpasswd -Bc registry.password username

    Ingrese la contraseña cuando se le solicite y la combinación de credenciales se agregará a registry.password.

    Nota: Para agregar más usuarios, vuelva a ejecutar el comando anterior sin -c, lo que crea un nuevo archivo:

    1. htpasswd -B registry.password username

    Ahora que la lista de credenciales está lista, deberá editarla docker-compose.ymlpara ordenar a Docker que use el archivo que creó para autenticar a los usuarios. Ábralo para editarlo ejecutando lo siguiente:

    1. nano ~/docker-registry/docker-compose.yml

    Añade las líneas resaltadas:

    ~/docker-registry/docker-compose.yml

    version: '3'services:  registry:    image: registry:2    ports:    - "5000:5000"    environment:      REGISTRY_AUTH: htpasswd      REGISTRY_AUTH_HTPASSWD_REALM: Registry      REGISTRY_AUTH_HTPASSWD_PATH: /auth/registry.password      REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data    volumes:      - ./auth:/auth      - ./data:/data

    Ha añadido variables de entorno que especifican el uso de la autenticación HTTP y ha proporcionado la ruta al archivo htpasswdcreado. Para REGISTRY_AUTH, ha especificado htpasswdcomo valor, que es el esquema de autenticación que está utilizando y ha establecido REGISTRY_AUTH_HTPASSWD_PATHla ruta del archivo de autenticación. REGISTRY_AUTH_HTPASSWD_REALMsignifica el nombre del htpasswddominio.

    También has montado el ./authdirectorio para que el archivo esté disponible dentro del contenedor de registro. Guarda y cierra el archivo.

    Ahora puedes comprobar que tu autenticación funciona correctamente. Primero, dirígete al directorio principal:

    1. cd ~/docker-registry

    Luego, ejecute el registro ejecutando:

    1. docker-compose up

    En tu navegador, actualiza la página de tu dominio. Se te solicitará un nombre de usuario y una contraseña.

    Después de proporcionar una combinación válida de credenciales, verá un objeto JSON vacío:

    {}

    Esto significa que se ha autenticado correctamente y ha obtenido acceso al registro. Salga presionando CTRL+C.

    Ahora su registro está protegido y solo se puede acceder a él después de la autenticación. Ahora lo configurará para que se ejecute como un proceso en segundo plano y sea resistente a los reinicios al iniciarse automáticamente.

    Paso 4: iniciar Docker Registry como servicio

    Puede asegurarse de que el contenedor de registro se inicie cada vez que se inicia el sistema o después de que se bloquea, instruyendo a Docker Compose para que lo mantenga siempre en ejecución. Abrir docker-compose.ymlpara editar:

    1. nano docker-compose.yml

    Añade la siguiente línea debajo del registrybloque:

    docker-compose.yml

    ...  registry:    restart: always...

    La configuración restartsiempre garantiza que el contenedor sobrevivirá a los reinicios. Cuando haya terminado, guarde y cierre el archivo.

    Ahora puede iniciar su registro como un proceso en segundo plano pasando -d:

    1. docker-compose up -d

    Con el registro ejecutándose en segundo plano, puedes cerrar libremente la sesión SSH y el registro no se verá afectado.

    Debido a que las imágenes de Docker pueden ser muy grandes, ahora aumentará el tamaño máximo de archivo que Nginx aceptará para las cargas.

    Paso 5: Aumentar el tamaño de carga de archivos para Nginx

    Antes de poder enviar una imagen al registro, debe asegurarse de que su registro pueda manejar cargas de archivos grandes.

    El límite de tamaño predeterminado para las cargas de archivos en Nginx es 1m, lo que no es suficiente para las imágenes de Docker. Para aumentarlo, deberá modificar el archivo de configuración principal de Nginx, ubicado en /etc/nginx/nginx.conf. Ábralo para editarlo ejecutando:

    1. sudo nano /etc/nginx/nginx.conf

    Busque la httpsección y agregue la siguiente línea:

    /etc/nginx/nginx.conf

    ...http {        client_max_body_size 16384m;        ...}...

    El client_max_body_sizeparámetro ahora está establecido en 16384m, lo que hace que el tamaño máximo de carga sea igual a 16 GB.

    Guarde y cierre el archivo cuando haya terminado.

    Reinicie Nginx para aplicar los cambios de configuración:

    1. sudo systemctl restart nginx

    Ahora puedes cargar imágenes grandes a tu Registro Docker sin que Nginx bloquee la transferencia o genere errores.

    Paso 6: Publicación en su registro privado de Docker

    Ahora que el servidor Docker Registry está en funcionamiento y acepta archivos de gran tamaño, puedes intentar enviarle una imagen. Como no tienes ninguna imagen disponible, usarás la ubuntuimagen de Docker Hub, un Docker Registry público, para realizar la prueba.

    Desde su segundo servidor cliente, ejecute el siguiente comando para descargar la ubuntuimagen, ejecutarla y obtener acceso a su shell:

    1. docker run -t -i ubuntu /bin/bash

    Los indicadores -iy -tle brindan acceso interactivo al shell del contenedor.

    Una vez que estés dentro, crea un archivo llamado SUCCESSejecutando:

    1. touch /SUCCESS

    Al crear este archivo, personalizaste tu contenedor. Más adelante lo usarás para comprobar que estás usando exactamente el mismo contenedor.

    Salga del shell del contenedor ejecutando:

    1. exit

    Ahora, crea una nueva imagen a partir del contenedor que acabas de personalizar:

    1. docker commit $(docker ps -lq) test-image

    La nueva imagen ya está disponible localmente y la enviarás a tu nuevo registro de contenedor. Primero, debes iniciar sesión:

    1. docker login https://your_domain

    Cuando se le solicite, ingrese la combinación de nombre de usuario y contraseña que haya definido en el paso 3 de este tutorial.

    La salida será:

    Output...Login Succeeded

    Una vez que haya iniciado sesión, cambie el nombre de la imagen creada:

    1. docker tag test-image your_domain/test-image

    Por último, envíe la imagen recién etiquetada a su registro:

    1. docker push your_domain/test-image

    Recibirá un resultado similar al siguiente:

    OutputThe push refers to a repository [your_domain/test-image]420fa2a9b12e: Pushedc20d459170d8: Pusheddb978cae6a05: Pushedaeb3f02e9374: Pushedlatest: digest: sha256:88e782b3a2844a8d9f0819dc33f825dde45846b1c5f9eb4870016f2944fe6717 size: 1150

    Verificó que su registro maneja la autenticación de usuarios mediante el inicio de sesión y permite que los usuarios autenticados envíen imágenes al registro. Ahora intentará extraer la imagen de su registro.

    Paso 7: extracción desde su registro privado de Docker

    Ahora que has subido una imagen a tu registro privado, intentarás extraerla de él.

    En el servidor principal, inicia sesión con el nombre de usuario y la contraseña que configuraste anteriormente:

    1. docker login https://your_domain

    Intente tirar del mismo test-imageejecutando:

    1. docker pull your_domain/test-image

    Docker debería descargar la imagen. Ejecute el contenedor con el siguiente comando:

    1. docker run -it your_domain/test-image /bin/bash

    Enumere los archivos presentes ejecutando:

    1. ls

    Verás el SUCCESSarchivo que has creado anteriormente, lo que confirma que es la misma imagen que has creado:

    SUCCESS  bin  boot  dev  etc  home  lib  lib64  media   mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

    Salga del shell del contenedor ejecutando:

    1. exit

    Ahora que ha probado a enviar y recibir imágenes, ha terminado de configurar un registro seguro que puede usar para almacenar imágenes personalizadas.

    Conclusión

    En este tutorial, configurará su propio registro Docker privado y publicará una imagen de Docker en él. Como se mencionó en la introducción, también puede usar TravisCI o una herramienta de integración continua similar para automatizar el envío a un registro privado directamente. Al aprovechar los contenedores Docker en su flujo de trabajo, puede asegurarse de que la imagen que contiene el código tenga el mismo comportamiento en cualquier máquina, ya sea en producción o en desarrollo. Para obtener más información sobre cómo escribir archivos Docker, puede visitar la documentación oficial sobre las mejores prácticas.

    SUSCRÍBETE A NUESTRO BOLETÍN 
    No te pierdas de nuestro contenido ni de ninguna de nuestras guías para que puedas avanzar en los juegos que más te gustan.

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

    Subir

    Este sitio web utiliza cookies para mejorar tu experiencia mientras navegas por él. Este sitio web utiliza cookies para mejorar tu experiencia de usuario. Al continuar navegando, aceptas su uso. Mas informacion