Cómo configurar un registro Docker privado en Rocky Linux 8
Si trabajas para una organización y quieres mantener tus imágenes Docker en casa para un despliegue rápido, entonces alojar un repositorio Docker privado es perfecto. Tener un registro Docker privado te permite ser dueño de tu canal de distribución de imágenes y tener un control más estricto sobre el almacenamiento y la distribución de imágenes. Puedes integrar tu registro con tu sistema CI/CD mejorando tu flujo de trabajo.
Este tutorial te enseñará a configurar y utilizar un registro Docker privado en un servidor basado en Rocky Linux 8 utilizando Amazon S3 como ubicación de almacenamiento.
Requisitos previos
- Dos servidores Linux con Rocky Linux 8. Un servidor actuará como anfitrión del registro, mientras que el otro se utilizará como cliente para enviar solicitudes y recibir imágenes del anfitrión.
- Un nombre de dominio registrado que apunte al servidor anfitrión. Utilizaremos
registry.example.com
para nuestro tutorial. - Un usuario no root con privilegios sudo en ambas máquinas.
Paso 1 – Configurar el cortafuegos
El primer paso es configurar el cortafuegos. Rocky Linux utiliza el cortafuegos Firewalld. Comprueba el estado del cortafuegos.
$ sudo firewall-cmd --state running
El cortafuegos funciona con diferentes zonas, y la zona pública es la que utilizaremos por defecto. Enumera todos los servicios y puertos activos en el cortafuegos.
$ sudo firewall-cmd --permanent --list-services
Debería mostrar el siguiente resultado.
cockpit dhcpv6-client ssh
Permite los puertos HTTP y HTTPS.
$ sudo firewall-cmd --permanent --add-service=http $ sudo firewall-cmd --permanent --add-service=https
Vuelve a comprobar el estado del cortafuegos.
$ sudo firewall-cmd --permanent --list-services
Deberías ver una salida similar.
cockpit dhcpv6-client http https ssh
Recarga el cortafuegos para activar los cambios.
$ sudo firewall-cmd --reload
Paso 2 – Instalar Docker y Docker Compose
Este paso es necesario tanto en el servidor como en las máquinas cliente.
Instala el repositorio oficial de Docker.
$ sudo dnf install yum-utils $ sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo
Instala Docker.
$ sudo dnf install docker-ce docker-ce-cli containerd.io
Habilita y ejecuta el demonio Docker.
$ sudo systemctl enable docker --now
Añade tu usuario del sistema al grupo Docker para evitar el uso de sudo
para ejecutar los comandos Docker.
$ sudo usermod -aG docker $(whoami)
Vuelve a conectarte a tu servidor después de cerrar la sesión para activar el cambio.
Descarga e instala la última versión estable de Docker Compose.
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
Aplica los permisos de ejecución al archivo binario descargado.
$ sudo chmod +x /usr/local/bin/docker-compose
Instala el script Docker-compose Bash Completion.
$ sudo curl \ -L https://raw.githubusercontent.com/docker/compose/1.29.2/contrib/completion/bash/docker-compose \ -o /etc/bash_completion.d/docker-compose
Recarga la configuración de tu perfil para que funcione el bash-completion.
$ source ~/.bashrc
Paso 3 – Configurar el Registro Docker
Crea directorios de usuario
Crea un directorio para la configuración del registro.
$ mkdir ~/docker-registry
Cambia al directorio docker-registry
.
$ cd ~/docker-registry
Crea un directorio para almacenar la contraseña de autenticación HTTP, los archivos de configuración de Nginx y los certificados SSL.
$ mkdir auth
Crea otro directorio para almacenar los registros de Nginx.
$ mkdir logs
Crea un cubo de Amazon S3
Puedes almacenar los datos del registro y las imágenes en tu servidor o utilizar un servicio de alojamiento en la nube. Para nuestro tutorial, utilizaremos el servicio en la nube Amazon S3.
El siguiente paso es establecer el archivo de configuración con algunos ajustes importantes. Estos ajustes también se pueden definir en el archivo docker-compose.yml
, pero es mucho mejor tener un archivo separado.
Crea un cubo con los siguientes ajustes.
- La ACL debe estar desactivada.
- El acceso público al cubo debe estar desactivado.
- El versionado del cubo debe estar deshabilitado.
- Habilita la encriptación del cubo utilizando las claves gestionadas de Amazon S3. (SSE-S3)
- El bloqueo de objetos debe estar deshabilitado.
Crea un usuario IAM con la siguiente política.
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:ListBucket", "s3:GetBucketLocation", "s3:ListBucketMultipartUploads" ], "Resource": "arn:aws:s3:::S3_BUCKET_NAME" }, { "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject", "s3:DeleteObject", "s3:ListMultipartUploadParts", "s3:AbortMultipartUpload" ], "Resource": "arn:aws:s3:::S3_BUCKET_NAME/*" } ] }
Sustituye el S3_BUCKET_NAME
por el nombre de tu cubo de S3.
Anota la clave secreta, el valor secreto y la región de tu cubo para utilizarla más adelante.
Crea el archivo Docker Compose
Crea el archivo docker-compose.yml
y ábrelo para editarlo.
$ nano docker-compose.yml
Pega en él el siguiente código.
version: '3.3' services: registry: image: registry:2 restart: always environment: - REGISTRY_STORAGE=s3 - REGISTRY_STORAGE_S3_REGION=us-west-2 - REGISTRY_STORAGE_S3_BUCKET=hf-docker-registry - REGISTRY_STORAGE_S3_ENCRYPT=true - REGISTRY_STORAGE_S3_CHUNKSIZE=5242880 - REGISTRY_STORAGE_S3_SECURE=true - REGISTRY_STORAGE_S3_ACCESSKEY=AKIA3FIG4NVFCJ6STMUA - REGISTRY_STORAGE_S3_SECRETKEY=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 - REGISTRY_STORAGE_S3_V4AUTH=true - REGISTRY_STORAGE_S3_ROOTDIRECTORY=/image-registry - REGISTRY_STORAGE_CACHE_BLOBDESCRIPTOR=inmemory - REGISTRY_HEALTH_STORAGEDRIVER_ENABLED=false nginx: image: "nginx:alpine" ports: - 443:443 links: - registry:registry volumes: - ./auth:/etc/nginx/conf.d - ./auth/nginx.conf:/etc/nginx/nginx.conf:ro - ./logs:/var/log/nginx - /etc/letsencrypt:/etc/letsencrypt
Guarda el archivo pulsando Ctrl + X e introduciendo Y cuando se te pida.
Repasemos lo que hemos configurado en nuestro archivo de composición.
-
El primer paso es coger la última imagen de la versión 2 del registro Docker del hub. No utilizamos la última etiqueta porque puede causar problemas en el caso de una actualización de versión mayor. Establecerla como 2 te permite obtener todas las actualizaciones de la versión 2.x y evitar que se actualice automáticamente a la siguiente versión mayor, lo que puede introducir cambios de ruptura.
-
El contenedor de registro está configurado para que se reinicie siempre en caso de fallo o cierre inesperado.
-
Hemos configurado varias variables de entorno para el almacenamiento de Amazon S3. Vamos a repasarlas rápidamente.
- REGISTRY_STORAGE establece el tipo de almacenamiento. Hemos seleccionado s3 ya que estamos utilizando Amazon S3.
- REGISTRY_STORAGE_S3_REGION establece la región de tu cubo S3.
- REGISTRY_STORAGE_S3_BUCKET establece el nombre de tu cubo S3.
- REGISTRY_STORAGE_S3_ENCRYPT – ponlo a true si has activado la encriptación del bucket.
- REGISTRY_STORAGE_S3_CHUNKSIZE establece el tamaño de los trozos de subida. Debe ser mayor que 5MB (5 * 1024 * 1024).
- REGISTRY_STORAGE_S3_SECURE – ponlo a true si vas a usar HTTPS.
- REGISTRY_STORAGE_S3_ACCESSKEY y REGISTRY_STORAGE_S3_SECRETKEY – credenciales de usuario que has obtenido tras crear tu usuario IAM.
- REGISTRY_STORAGE_S3_V4AUTH – ponlo a true si utilizas la v4 de la autenticación de AWS. Si obtienes errores relacionados con el inicio de sesión en S3, establécelo como falso.
- REGISTRY_STORAGE_S3_ROOTDIRECTORY – establece el directorio raíz de tu cubo en el que se almacenarán tus datos de registro.
- REGISTRY_STORAGE_CACHE_BLOBDESCRIPTOR – establece la ubicación de la Caché. En nuestro caso, la almacenamos en la memoria. También puedes configurarlo para utilizar Redis.
- REGISTRY_HEALTH_STORAGEDRIVER_ENABLED – Ponlo a false para desactivar el servicio de comprobación de la salud del almacenamiento del Registro. Hay un error en el Registro que puede causar problemas si no lo pones en falso.
-
El registro Docker se comunica a través del puerto 5000, que es el que hemos expuesto en nuestro servidor al docker.
-
./auth:/etc/nginx/conf.d
El mapeo asegura que todas las configuraciones de Nginx estén disponibles en el contenedor. -
./auth/nginx.conf:/etc/nginx/nginx.conf:ro
mapea el archivo de configuración de Nginx del sistema a uno del contenedor en modo de sólo lectura. -
./logs:/var/log/nginx
permite el acceso a los registros de Nginx en el sistema mediante el mapeo al directorio de registros de Nginx en el contenedor. -
La configuración del registro Docker se almacena en el archivo
/etc/docker/registry/config.yml
en el contenedor, y lo hemos mapeado al archivoconfig.yml
en el directorio actual, que crearemos en el siguiente paso.
Configurar la autenticación
Para configurar la autenticación HTTP, necesitas instalar el paquete httpd-tools
.
$ sudo dnf install httpd-tools
Crea el archivo de contraseña en el directorio ~/docker-registry/auth
.
$ htpasswd -Bc ~/docker-registry/auth/nginx.htpasswd user1 New password: Re-type new password: Adding password for user user1
La bandera -c
indica al comando que cree un nuevo archivo, y la bandera -B
es para utilizar el algoritmo bcrypt soportado por Docker. Sustituye user1
por un nombre de usuario de tu elección.
Si quieres añadir más usuarios, ejecuta el comando de nuevo, pero sin la bandera -c
.
$ htpasswd -B ~/docker-registry/auth/registry.password user2
Ahora, el archivo se asignará al contenedor de registro para la autenticación.
Paso 4 – Instalar SSL
Para instalar un certificado SSL con Let’s Encrypt, necesitamos descargar la herramienta Certbot, que está disponible en el repositorio de Epel.
Instala el repositorio EPEL y Certbot.
$ sudo dnf install epel-release $ sudo dnf install certbot
Genera un certificado SSL.
$ sudo certbot certonly --standalone --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m [email protected] -d registry.example.com
El comando anterior descargará un certificado en el directorio /etc/letsencrypt/live/registry.example.com
de tu servidor.
Genera un certificado de grupo Diffie-Hellman.
$ sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096
Prueba la renovación del certificado.
$ sudo certbot renew --dry-run
Si la prueba en seco tiene éxito, significa que tus certificados se renovarán automáticamente.
Copia el archivo Dhparam en el contenedor
Copia el certificado de grupo Diffie-Hellman en el directorio ~/docker-registry/auth
, que se asignará al contenedor.
$ sudo cp /etc/ssl/certs/dhparam.pem ~/docker-registry/auth
Paso 5 – Configurar Nginx
El siguiente paso consiste en configurar el servidor Nginx como proxy del front-end para el servidor de registro de Docker. El registro de Docker viene con un servidor incorporado que opera en el puerto 5000. Lo pondremos detrás de Nginx.
Crea y abre el archivo ~/docker-registry/auth/nginx.conf
para editarlo.
$ sudo nano ~/docker-registry/auth/nginx.conf
Pega en él el siguiente código.
events { worker_connections 1024; } http { upstream docker-registry { server registry:5000; } ## Set a variable to help us decide if we need to add the ## 'Docker-Distribution-Api-Version' header. ## The registry always sets this header. ## In the case of nginx performing auth, the header is unset ## since nginx is auth-ing before proxying. map $upstream_http_docker_distribution_api_version $docker_distribution_api_version { '' 'registry/2.0'; } server { listen 443 ssl http2; server_name registry.example.com; # SSL ssl_certificate /etc/letsencrypt/live/registry.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/registry.example.com/privkey.pem; ssl_trusted_certificate /etc/letsencrypt/live/registry.example.com/chain.pem; access_log /var/log/nginx/registry.access.log; error_log /var/log/nginx/registry.error.log; # Recommendations from https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html 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 on; ssl_ecdh_curve X25519:prime256v1:secp384r1:secp521r1; ssl_session_cache shared:SSL:10m; ssl_dhparam /etc/nginx.d/conf.d/dhparam.pem; resolver 8.8.8.8; # disable any limits to avoid HTTP 413 for large image uploads client_max_body_size 0; # required to avoid HTTP 411: see Issue #1486 (https://github.com/moby/moby/issues/1486) chunked_transfer_encoding on; location /v2/ { # 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; } # To add basic authentication to v2 use auth_basic setting. auth_basic "Registry realm"; auth_basic_user_file /etc/nginx/conf.d/nginx.htpasswd; ## If $docker_distribution_api_version is empty, the header is not added. ## See the map directive above where this variable is defined. add_header 'Docker-Distribution-Api-Version' $docker_distribution_api_version always; proxy_pass http://docker-registry; 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; } } }
Guarda el archivo pulsando Ctrl + X e introduciendo Y cuando te lo pida una vez hayas terminado.
Configura SELinux para permitir las conexiones de red para el Registro Docker Privado.
$ sudo setsebool -P httpd_can_network_connect on
Paso 6 – Iniciar el Registro Docker
Cambia al directorio del Registro Docker.
$ cd ~/docker-registry
Lanza el contenedor Docker.
$ docker-compose up -d
Comprueba el estado de los contenedores.
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 88d6addc1687 nginx:alpine "/docker-entrypoint.…" 5 minutes ago Up 5 minutes 80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp docker-registry_nginx_1 2b112edc1c72 registry:2 "/entrypoint.sh /etc…" 5 minutes ago Up 5 minutes 5000/tcp docker-registry_registry_1
Accede al registro Docker.
$ docker login -u=testuser -p=testpassword https://registry.example.com
También puedes abrir la URL https://registry.example.com/v2/
en tu navegador, y te pedirá un nombre de usuario y una contraseña. Deberías ver una página vacía con {}.
Puedes comprobar la URL en el terminal utilizando curl
.
$ curl -u testuser -X GET https://registry.nspeaks.xyz/v2/ Enter host password for user 'testuser': {}
Descarga la última imagen docker de Ubuntu.
$ docker pull ubuntu:latest
Marca esta imagen para el registro privado.
$ docker tag ubuntu:latest registry.example.com/ubuntu2004
Empuja la imagen al registro.
$ docker push registry.example.com/ubuntu2004
Comprueba si el push se ha realizado con éxito.
$ curl -u testuser -X GET https://registry.nspeaks.xyz/v2/_catalog Enter host password for user 'testuser': {"repositories":["ubuntu2004"]}
Introduce tu contraseña de autenticación de Nginx cuando se te pida, y verás la lista de repositorios disponibles a través del registro.
Comprueba la lista de imágenes Docker disponibles actualmente para su uso.
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE registry 2 d3241e050fc9 5 days ago 24.2MB nginx alpine 53722defe627 5 days ago 23.4MB httpd 2 118b6abfbf55 5 days ago 144MB ubuntu latest ff0fea8310f3 2 weeks ago 72.8MB registry.nspeaks.xyz/ubuntu2004 latest ff0fea8310f3 2 weeks ago 72.8MB
Paso 7 – Acceder y utilizar el registro Docker desde la máquina cliente
Accede a tu servidor-cliente. En el paso 1, hemos instalado Docker en la máquina cliente.
Accede al registro privado de Docker desde la máquina cliente.
$ docker login -u=testuser -p=testpassword https://registry.example.com
Saca la imagen de Ubuntu del registro.
$ docker pull registry.example.com/ubuntu2004
Enumera todas las imágenes de tu máquina cliente.
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE registry.nspeaks.xyz/ubuntu2004 latest ff0fea8310f3 2 weeks ago 72.8MB
Crea y lanza un contenedor con la imagen descargada.
$ docker run -it registry.example.com/ubuntu2004 /bin/bash
Entrarás en el Shell dentro del contenedor de Ubuntu.
root@a2da49fdbea9:
Ejecuta el siguiente comando para comprobar la versión de Linux.
root@a2da49fdbea9$ cat /etc/os-release NAME="Ubuntu" VERSION="20.04.4 LTS (Focal Fossa)" ID=ubuntu ID_LIKE=debian PRETTY_NAME="Ubuntu 20.04.4 LTS" VERSION_ID="20.04" HOME_URL="https://www.ubuntu.com/" SUPPORT_URL="https://help.ubuntu.com/" BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy" VERSION_CODENAME=focal UBUNTU_CODENAME=focal
Ahora, puedes empezar a utilizar tu registro Docker desde tus máquinas cliente.
Conclusión
Con esto concluye nuestro tutorial sobre la configuración de un registro Docker privado en un servidor basado en Rocky Linux 8 que utiliza Amazon S3 como almacenamiento. Si tienes alguna pregunta, publícala en los comentarios de abajo.