tutoriales.com

Configurando un Registro Privado de Docker con Docker Registry y Nginx: Almacena tus Imágenes de Forma Segura

Este tutorial te guiará paso a paso en la configuración de un registro privado de Docker, utilizando el servicio oficial Docker Registry y Nginx como proxy inverso para añadir seguridad con TLS/SSL y autenticación básica. Aprenderás a desplegarlo, subir imágenes y acceder a ellas desde otros entornos, garantizando la privacidad y el control sobre tus imágenes de contenedor.

Intermedio20 min de lectura8 views
Reportar error

🚀 Introducción a los Registros Privados de Docker

En el ecosistema Docker, los registros son servicios fundamentales que almacenan y distribuyen imágenes de contenedores. Docker Hub es el registro público más conocido, pero a menudo, las organizaciones necesitan gestionar sus propias imágenes de forma privada. Esto es especialmente cierto para imágenes que contienen código propietario, dependencias internas o configuraciones sensibles que no deben ser accesibles públicamente.

Un registro privado de Docker ofrece varias ventajas clave:

  • Seguridad y Privacidad: Control total sobre quién puede acceder y descargar tus imágenes.
  • Cumplimiento: Facilita el cumplimiento de normativas de seguridad y privacidad de datos.
  • Control de Versiones: Mejora la gestión y el control de versiones de tus imágenes internas.
  • Rendimiento: Reduce la latencia de descarga para equipos internos al mantener las imágenes más cerca de tu infraestructura.
  • Personalización: Permite integrar el registro con tus sistemas de CI/CD y flujos de trabajo existentes.

Este tutorial te mostrará cómo configurar un registro privado de Docker desde cero, utilizando el contenedor registry oficial de Docker y añadiendo una capa de seguridad y control de acceso con Nginx. Nginx actuará como un proxy inverso, permitiéndonos implementar TLS/SSL para conexiones seguras (HTTPS) y autenticación básica para restringir el acceso.

🎯 Requisitos Previos

Antes de empezar, asegúrate de tener lo siguiente:

  • Un servidor con Docker instalado y funcionando. Puedes seguir la documentación oficial de Docker para tu sistema operativo.
  • Acceso sudo o root en el servidor.
  • Conocimientos básicos de Docker y Nginx serán útiles, pero no son estrictamente necesarios.
  • Un nombre de dominio apuntando a la IP de tu servidor (por ejemplo, registry.tudominio.com) si deseas usar certificados TLS/SSL válidos de Let's Encrypt. Si es para uso local o de prueba, puedes usar una IP o un dominio autoseñalado.
📌 Nota: Para este tutorial, asumiremos que estás configurando el registro en un servidor Linux. Los comandos pueden variar ligeramente en otros sistemas operativos.

🛠️ Paso 1: Configurando el Entorno y Directorios

Primero, crearemos los directorios necesarios en el servidor para almacenar los datos del registro y la configuración de Nginx. Esto asegura que los datos sean persistentes y no se pierdan si el contenedor del registro se detiene o se elimina.

sudo mkdir -p /opt/docker-registry/data
sudo mkdir -p /opt/docker-registry/auth
sudo mkdir -p /opt/docker-registry/certs
sudo mkdir -p /opt/docker-registry/nginx
  • /opt/docker-registry/data: Aquí se almacenarán todas las imágenes Docker que subas al registro.
  • /opt/docker-registry/auth: Aquí guardaremos el archivo de credenciales para la autenticación básica de Nginx.
  • /opt/docker-registry/certs: Aquí irán los certificados SSL/TLS para Nginx (si usas HTTPS).
  • /opt/docker-registry/nginx: Aquí pondremos el archivo de configuración de Nginx.

🔐 Paso 2: Generando Credenciales para Nginx (Autenticación Básica)

Vamos a proteger nuestro registro con autenticación básica de HTTP usando Nginx. Necesitarás el paquete apache2-utils para generar el archivo .htpasswd.

sudo apt update
sudo apt install -y apache2-utils

Ahora, crea el archivo de credenciales. Reemplaza tousuario con el nombre de usuario que desees. Se te pedirá que introduzcas y confirmes la contraseña.

sudo htpasswd -Bc /opt/docker-registry/auth/htpasswd tousuario
💡 Consejo: Usa contraseñas fuertes y únicas. Considera rotarlas periódicamente para una mayor seguridad.

🛡️ Paso 3: Configurando SSL/TLS (HTTPS)

Usar HTTPS es crucial para la seguridad de tu registro privado, ya que encripta la comunicación entre el cliente Docker y el registro, protegiendo tus credenciales y el contenido de tus imágenes. Hay dos opciones:

Opción A: Certificados de Let's Encrypt (Recomendado para Producción)

Esta es la opción más segura y profesional. Necesitarás un nombre de dominio apuntando a tu servidor. Usaremos certbot para generar los certificados. Si ya tienes Nginx instalado y funcionando, puedes seguir los pasos de Certbot para Nginx. Si no, generaremos los certificados de forma independiente.

Para este tutorial, asumiremos que Nginx no está corriendo en el puerto 80/443 todavía, lo que nos permite usar el standalone plugin de Certbot.

sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo certbot certonly --standalone -d registry.tudominio.com --agree-tos --email tuemail@ejemplo.com --non-interactive

Reemplaza registry.tudominio.com y tuemail@ejemplo.com con tus datos. Los certificados se guardarán en /etc/letsencrypt/live/registry.tudominio.com/.

Luego, copiamos los certificados a nuestro directorio configurado para Nginx:

sudo cp /etc/letsencrypt/live/registry.tudominio.com/fullchain.pem /opt/docker-registry/certs/registry.crt
sudo cp /etc/letsencrypt/live/registry.tudominio.com/privkey.pem /opt/docker-registry/certs/registry.key
sudo chmod 600 /opt/docker-registry/certs/registry.key

Opción B: Certificados Autoseñalados (Para Desarrollo/Pruebas)

Si no tienes un dominio o solo necesitas un registro para pruebas internas, puedes crear certificados autoseñalados. Sin embargo, los clientes Docker necesitarán ser configurados para confiar en estos certificados, lo que añade un paso adicional.

sudo openssl req -newkey rsa:2048 -nodes -keyout /opt/docker-registry/certs/registry.key -x509 -days 365 -out /opt/docker-registry/certs/registry.crt

Cuando se te pregunte por el Common Name (e.g. server FQDN or YOUR name), asegúrate de introducir el nombre de host o la dirección IP que usarás para acceder al registro (por ejemplo, registry.tudominio.com o la IP de tu servidor).

⚠️ Advertencia: Los certificados autoseñalados NO son seguros para entornos de producción. Utilízalos solo para desarrollo o pruebas.

⚙️ Paso 4: Configuración de Nginx

Crearemos un archivo de configuración para Nginx que actuará como proxy inverso para nuestro registro Docker.

Crea el archivo /opt/docker-registry/nginx/registry.conf con el siguiente contenido. Asegúrate de ajustar registry.tudominio.com a tu nombre de dominio (o la IP si usas certificados autoseñalados).

upstream docker-registry {
    server registry:5000;
}

server {
    listen 80;
    server_name registry.tudominio.com;

    # Redirigir todo el tráfico HTTP a HTTPS
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name registry.tudominio.com;

    # SSL
    ssl_certificate /etc/nginx/certs/registry.crt;
    ssl_certificate_key /etc/nginx/certs/registry.key;

    # Configuración de SSL estándar (recomendado por Mozilla TLS config generator)
    ssl_session_cache shared:SSL:10m;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
    ssl_prefer_server_ciphers off;

    # Autenticación básica
    auth_basic "Acceso Restringido al Docker Registry";
    auth_basic_user_file /etc/nginx/auth/htpasswd;

    client_max_body_size 0; # Permite subir imágenes de cualquier tamaño
    chunked_transfer_encoding on;

    location / {
        # Proxy al contenedor de Docker Registry
        proxy_pass http://docker-registry;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 900;
        
        # Headers necesarios para el Docker Registry API
        proxy_set_header Authorization ""; # Eliminar header auth para el backend
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
    }
}
🔥 Importante: La línea `proxy_set_header Authorization "";` es crucial. Nginx maneja la autenticación básica y no necesitamos pasar las credenciales al backend del registro, que no las espera de esta manera.

🐳 Paso 5: Desplegando el Registro y Nginx con Docker Compose

Para simplificar la gestión de ambos contenedores (el registro y Nginx), utilizaremos Docker Compose. Crea un archivo docker-compose.yml en /opt/docker-registry/:

version: '3.8'

services:
  registry:
    image: registry:2
    restart: always
    ports:
      - "5000:5000"
    volumes:
      - ./data:/var/lib/registry # Persistencia de imágenes
      - ./certs:/etc/docker/registry/certs # Opcional: para configuraciones avanzadas del registro
    environment:
      REGISTRY_HTTP_ADDR: 0.0.0.0:5000
      # Si usas HTTPS directamente en el registry sin Nginx (NO recomendado aquí):
      # REGISTRY_HTTP_TLS_CERTIFICATE: /etc/docker/registry/certs/registry.crt
      # REGISTRY_HTTP_TLS_KEY: /etc/docker/registry/certs/registry.key

  nginx:
    image: nginx:stable-alpine
    restart: always
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/registry.conf:/etc/nginx/conf.d/default.conf:ro # Configuración de Nginx
      - ./auth:/etc/nginx/auth:ro             # Archivo .htpasswd
      - ./certs:/etc/nginx/certs:ro           # Certificados SSL/TLS
    depends_on:
      - registry # Asegura que el registro inicie antes que Nginx

Navega al directorio /opt/docker-registry/ y levanta los servicios:

cd /opt/docker-registry/
sudo docker compose up -d

Verifica que los contenedores estén funcionando:

sudo docker compose ps

Deberías ver ambos servicios (registry y nginx) con estado Up.

/certs /auth Cliente Docker CLI / Navegador Nginx Proxy Puerto 443 (SSL/TLS) Auth Básica Docker Registry Puerto 5000 Almacén de Datos HTTPS HTTP Volumen Infraestructura de Registro Privado Seguro con Nginx y Docker

✅ Paso 6: Configurando el Cliente Docker para Confiar en el Registro

Para que tu cliente Docker pueda interactuar con el registro privado, especialmente si usas certificados autoseñalados, necesitarás configurarlo para confiar en tu certificado.

Para Certificados de Let's Encrypt

Si usaste Let's Encrypt, tu sistema operativo ya debería confiar en estos certificados, por lo que no es necesario realizar ninguna configuración adicional del lado del cliente. ¡Directamente al paso 7!

Para Certificados Autoseñalados

Si creaste un certificado autoseñalado, el cliente Docker no confiará en él por defecto. Necesitas copiar el certificado público (registry.crt) al directorio de certificados de confianza de Docker en la máquina cliente (donde ejecutarás docker push/pull).

En la máquina cliente (no en el servidor del registro):

sudo mkdir -p /etc/docker/certs.d/registry.tudominio.com # Reemplaza con tu dominio/IP
sudo cp /ruta/a/tu/registry.crt /etc/docker/certs.d/registry.tudominio.com/ca.crt

# Reinicia Docker para aplicar los cambios
sudo systemctl restart docker

Si estás usando una dirección IP en lugar de un dominio, la ruta sería /etc/docker/certs.d/<TU_IP>. Recuerda que el Common Name de tu certificado debe coincidir con esta IP o dominio.

⬆️ Paso 7: Probando el Registro: Subir y Descargar Imágenes

Ahora es el momento de probar nuestro registro. Primero, iniciamos sesión.

docker login registry.tudominio.com

Se te pedirá el nombre de usuario y la contraseña que configuraste con htpasswd.

7.1. Subir una Imagen (Push)

Vamos a descargar una imagen pequeña y luego la etiquetaremos y subiremos a nuestro registro.

  1. Descargar una imagen de prueba:
docker pull hello-world
  1. Etiquetar la imagen para tu registro:
docker tag hello-world registry.tudominio.com/mi-hello-world:latest
Asegúrate de reemplazar `registry.tudominio.com` con tu dirección de registro.

3. Subir la imagen a tu registro:

docker push registry.tudominio.com/mi-hello-world:latest

Si todo está configurado correctamente, la imagen se subirá sin problemas.

7.2. Descargar una Imagen (Pull)

Para probar la descarga, primero eliminaremos la imagen localmente y luego la descargaremos de tu registro.

  1. Eliminar la imagen localmente:
docker rmi registry.tudominio.com/mi-hello-world:latest
docker rmi hello-world
  1. Descargar la imagen de tu registro:
docker pull registry.tudominio.com/mi-hello-world:latest

Si la descarga es exitosa, ¡felicidades! Has configurado tu registro privado de Docker con éxito.

🔍 Verificando Contenido del Registro (Opcional)

Para ver las imágenes almacenadas en tu registro, puedes usar la API V2 del registro. Necesitarás curl y la autenticación adecuada.

curl -u tousuario:tupassword https://registry.tudominio.com/v2/_catalog

Esto debería devolver un JSON listando los repositorios disponibles en tu registro:

{
  "repositories": [
    "mi-hello-world"
  ]
}

Para ver los tags de una imagen específica:

curl -u tousuario:tupassword https://registry.tudominio.com/v2/mi-hello-world/tags/list
{
  "name": "mi-hello-world",
  "tags": [
    "latest"
  ]
}

🔄 Mantenimiento y Gestión del Registro

Renovación de Certificados Let's Encrypt

Si utilizaste Let's Encrypt, los certificados caducan cada 90 días. Es vital configurarlos para que se renueven automáticamente.

sudo certbot renew --dry-run

Esto probará el proceso de renovación. Si funciona, puedes crear un cron job para que se ejecute regularmente. Después de la renovación, deberás copiar los nuevos certificados al directorio de Nginx y reiniciar Nginx. Una forma sencilla de automatizarlo es añadir un hook a certbot.

Edita el archivo de cron:

sudo crontab -e

Añade la siguiente línea (ajusta la hora según necesites):

0 3 * * * /usr/bin/certbot renew --post-hook "cp /etc/letsencrypt/live/registry.tudominio.com/fullchain.pem /opt/docker-registry/certs/registry.crt && cp /etc/letsencrypt/live/registry.tudominio.com/privkey.pem /opt/docker-registry/certs/registry.key && docker compose restart nginx -f /opt/docker-registry/docker-compose.yml"
⚠️ Advertencia: Asegúrate de que las rutas y el comando `docker compose restart` sean correctos para tu configuración.

Limpieza del Almacenamiento

Con el tiempo, tu registro acumulará imágenes. Docker Registry ofrece una funcionalidad de recolección de basura para eliminar capas de imágenes no referenciadas.

  1. Eliminar imágenes no deseadas (del índice, no del disco aún):
docker rmi registry.tudominio.com/mi-hello-world:oldtag
Esto solo elimina el *tag* o la imagen de la vista lógica del registro.

2. Ejecutar la recolección de basura: Primero, detén el contenedor del registro:

sudo docker compose stop registry
Luego, ejecuta el comando `garbage-collect` del registro (usando el mismo volumen de datos):
sudo docker run --rm -it \
-v /opt/docker-registry/data:/var/lib/registry \
registry:2 garbage-collect /etc/docker/registry/config.yml
<div class="callout warning">⚠️ <strong>Advertencia:</strong> Asegúrate de que el registro no esté en uso durante la recolección de basura, ya que podría corromper el repositorio si se está escribiendo.</div>
Finalmente, vuelve a iniciar el registro:
sudo docker compose start registry

Actualización del Registro

Para actualizar el contenedor del registry o nginx a una versión más reciente, simplemente detén los servicios, elimina los contenedores existentes, descarga las nuevas imágenes y vuélvelos a levantar:

cd /opt/docker-registry/
sudo docker compose down
sudo docker compose pull
sudo docker compose up -d

Los datos de tus imágenes (/opt/docker-registry/data) y las configuraciones se mantendrán gracias a los volúmenes.

💡 Consideraciones Adicionales y Mejores Prácticas

  • Almacenamiento: Para entornos de producción, considera usar un backend de almacenamiento distribuido o en la nube (como S3, GCS, Azure Blob Storage) en lugar del almacenamiento local. El Docker Registry soporta varias opciones de backend a través de variables de entorno.
  • Monitorización: Integra tu registro con herramientas de monitorización (Prometheus, Grafana) para observar su rendimiento y estado.
  • Backup: Implementa una estrategia de backup para el directorio /opt/docker-registry/data para evitar la pérdida de datos.
  • Firewall: Configura el firewall de tu servidor para permitir solo el tráfico HTTP (puerto 80) y HTTPS (puerto 443) entrante, y restringe el acceso al puerto 5000 internamente para Nginx.
  • CI/CD: Integra tu registro privado en tus pipelines de integración y entrega continua para automatizar el build, push y pull de imágenes.
  • Escalabilidad: Para alta disponibilidad y escalabilidad, puedes ejecutar múltiples instancias del registro detrás de un balanceador de carga, aunque la configuración del almacenamiento se vuelve más compleja.
Configuración Completa

Este tutorial te ha proporcionado una base sólida para configurar tu propio registro privado de Docker. Con esta infraestructura, tienes un control total sobre tus imágenes, lo que es esencial para cualquier flujo de trabajo de DevOps serio.

Tutoriales relacionados

Comentarios (0)

Aún no hay comentarios. ¡Sé el primero!