El autor seleccionó la Apache Software Foundation para recibir una donación como parte del programa Write for DOnations.
Docker Registry es una aplicación que gestiona el almacenamiento y el envío de imágenes de contenedores de Docker. Los registros centralizan las imágenes de contenedores y reducen el tiempo 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 crear una imagen puede suponer una inversión significativa en términos de tiempo. Por ejemplo, en vez de instalar dependencias y paquetes por separado para usar Docker, los desarrolladores pueden descargar una imagen comprimida de un registro que contenga todos los componentes necesarios. Además, los desarrolladores pueden automatizar la introducción de imágenes en un registro usando herramientas de integración continua, como TravisCI, para actualizar imágenes sin problemas durante la producción y el desarrollo.
Docker también tiene un registro público gratuito, Docker Hub, que puede alojar sus imágenes de Docker personalizadas, pero existen situaciones en las que no le convendrá que su imagen esté disponible públicamente. Las imágenes normalmente contienen todo el código necesario para ejecutar una aplicación. Por lo tanto, usar un registro privado es preferible cuando se utiliza software propio.
A través de este tutorial, configurará y protegerá su propio Docker Registry privado. Usará Docker Compose para definir las configuraciones a fin de ejecutar Nginx y sus aplicaciones de Docker para reenviar el tráfico del servidor de HTTPS al contenedor de Docker en ejecución. Una vez que complete este tutorial, podrá introducir una imagen de Docker personalizada en su registro privado y extraer la imagen de forma segura desde un servidor remoto.
Antes de iniciar esta guía, necesitará lo siguiente:
La herramienta de línea de comandos de Docker es útil para iniciar y administrar uno o dos contenedores de Docker. Sin embargo, para una implementación completa la mayoría de las aplicaciones que se ejecutan dentro de contenedores de Docker requieren que otros componentes se ejecuten en paralelo. Por ejemplo, muchas aplicaciones web constan de un servidor web, como Nginx, que presente el código de la aplicación, un lenguaje de creación de secuencia de comandos interpretado como PHP, y un servidor de base de datos como MySQL.
Con Docker Compose, puede escribir un archivo .yml
para configurar los ajustes de cada uno de los contenedores y la información que estos deben transmitirse entre sí. Puede usar la herramienta de línea de comandos docker-componse
para emitir comandos a todos los componentes que forman su aplicación.
Docker Registry es en sí misma una aplicación con varios componentes, por lo que utilizará Docker Compose para administrar su configuración. Para iniciar una instancia del registro, configurará un archivo docker-compose.yml
para definir la ubicación en la que su registro almacenará sus datos.
En el servidor que creó para alojar su Docker Registry privado, puede crear un directorio docker-registry
, moverlo a él, y luego crear una subcarpeta data
con los siguientes comandos:
- mkdir ~/docker-registry && cd $_
- mkdir data
Utilice su editor de texto para crear el archivo de configuración docker-compose.yml
:
- nano docker-compose.yml
Añada el siguiente contenido al archivo, que describe la configuración básica para un Docker Registry:
version: '3'
services:
registry:
image: registry:2
ports:
- "5000:5000"
environment:
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
volumes:
- ./data:/data
En la sección environment
se establece una variable de entorno en el contenedor de Docker Registry con la ruta /data
. La aplicación Docker Registry verifica esta variable de entorno cuando se inicia, y como resultado, comienza a guardar sus datos en la carpeta /data
.
Sin embargo, debido a que incluyó la línea volumes: - ./data:/data
, Docker comenzará a asignar el directorio /data
de ese contenedor a /data
en su servidor de registro. Como resultado final, los datos de Docker Registry se almacenan en ~/docker-registry/data
en el servidor de registro.
La sección ports
, con la configuración 5000:5000
, indica a Docker que asigne el puerto 5000
en el servidor al puerto 5000
en el contenedor en ejecución. Esto le permite enviar una solicitud al puerto 5000
en el servidor, y que la solicitud se reenvíe a la aplicación de registro.
Ahora puede iniciar Docker Compose para comprobar la configuración:
- docker-compose up
Verá las barras de descarga en su resultado, que muestran que Docker está descargando la imagen de Docker Registry del registro propio de Docker. En un minuto o dos, verá un resultado similar al siguiente (las versiones pueden variar):
Output of docker-compose upStarting docker-registry_registry_1 ... done
Attaching to docker-registry_registry_1
registry_1 | time="2018-11-06T18:43:09Z" 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.7.6 instance.id=c63483ee-7ad5-4205-9e28-3e809c843d42 version=v2.6.2
registry_1 | time="2018-11-06T18:43:09Z" level=info msg="redis not configured" go.version=go1.7.6 instance.id=c63483ee-7ad5-4205-9e28-3e809c843d42 version=v2.6.2
registry_1 | time="2018-11-06T18:43:09Z" level=info msg="Starting upload purge in 20m0s" go.version=go1.7.6 instance.id=c63483ee-7ad5-4205-9e28-3e809c843d42 version=v2.6.2
registry_1 | time="2018-11-06T18:43:09Z" level=info msg="using inmemory blob descriptor cache" go.version=go1.7.6 instance.id=c63483ee-7ad5-4205-9e28-3e809c843d42 version=v2.6.2
registry_1 | time="2018-11-06T18:43:09Z" level=info msg="listening on [::]:5000" go.version=go1.7.6 instance.id=c63483ee-7ad5-4205-9e28-3e809c843d42 version=v2.6.2
Abordará el mensaje de advertencia No HTTP secret provided
posteriormente en este tutorial. El resultado muestra que el contenedor se está iniciando. La última línea del resultado muestra que comenzó a escuchar correctamente en el puerto 5000
.
Por defecto, Docker Compose esperará su intervención. Por ello, pulse CTRL+C
para apagar su contenedor de Docker Registry.
Configuró una escucha completa de Docker Registry en el puerto 5000
. En este momento, el registro no se iniciará a menos que lo abra manualmente. Además, Docker Registry no tiene ningún mecanismo de autenticación incorporado, por lo que actualmente no es seguro y está completamente abierto al público. En los siguientes pasos, abordará estos problemas de seguridad.
Ya tiene HTTPS configurado en su servidor de Docker Registry con Nginx, lo que significa que ahora puede configurar el enrutamiento de puertos de Nginx al puerto 5000
. Una vez que complete este paso, podrá acceder a su registro directamente en example.com.
Como parte del requisito previo de Cómo proteger Nginx con Let´s Encrypt, ya configuró el archivo /etc/nginx/sites-available/example.com
que contiene la configuración de su servidor.
Abra este archivo con su editor de texto:
- sudo nano /etc/nginx/sites-available/example.com
Encuentre la línea location
existente. Tendrá el siguiente aspecto:
...
location / {
...
}
...
Deberá reenviar el tráfico al puerto 5000
, donde se ejecutará su registro. También le conviene adjuntar encabezados a la solicitud al registro, que proporcionan información adicional desde el servidor con cada solicitud y respuesta. Elimine el contenido de la sección location
, y añada el siguiente contenido a dicha sección:
...
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;
}
...
La sección $http_user_agent
verifica que la versión de Docker del cliente sea superior a la 1.5
y garantiza que UserAgent
no sea una aplicación de Go
. Debido a que usa la versión 2.0
del registro, los clientes más antiguos no son compatibles. Para obtener más información, puede encontrar la configuración de encabezados nginx
en la guía Nginx Docker Registry.
Guarde el archivo y ciérrelo. Aplique los cambios reiniciando Nginx:
- sudo service nginx restart
Puede confirmar que Nginx enrute el tráfico al puerto 5000
ejecutando el registro:
- cd ~/docker-registry
- docker-compose up
En una ventana del navegador, abra la siguiente URL:
https://example.com/v2
Verá un objeto JSON vacío, o lo siguiente:
{}
En su terminal, verá un resultado similar al siguiente:
Output of docker-compose upregistry_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.2
registry_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"
Puede ver la última línea desde la cual se realizó una solicitud GET
a /v2/
, que es el punto final al que envío la solicitud desde su navegador. El contenedor recibió la solicitud que realizó, desde el puerto del enrutamiento, y devolvió una respuesta {}
. El código 200
en la última línea del resultado significa que el contenedor gestionó la solicitud correctamente.
Ahora que configuró el enrutamiento de puertos, puede mejorar la seguridad de su registro.
Con las solicitudes de proxy de Nginx, puede proteger su registro con autenticación HTTP para administrar el acceso a su Docker Registry. Para conseguir esto, creará un archivo de autenticación con htpasswd
y le añadirá usuarios. La autenticación HTTP se configura rápidamente y es segura a través de una conexión HTTPS, que es la que el registro usará.
Puede instalar el paquete htpasswd
ejecutando lo siguiente:
- sudo apt install apache2-utils
Ahora creará el directorio en el que almacenará nuestras credenciales de autenticación y se posicionará en ese directorio. $
se expande al último argumento del comando anterior; en este caso, ~/docker-registry/auth
:
- mkdir ~/docker-registry/auth && cd $_
A continuación, creará el primer usuario de como se muestra a continuación, sustituyendo username
por el nombre de usuario que desee usar. El indicador -B
especifica el cifrado bcrypt
, que es más seguro que el cifrado predeterminado. Introduzca la contraseña cuando se le solicite:
- htpasswd -Bc registry.password username
**Nota: **Para agregar más usuarios, vuelva a ejecutar el comando anterior sin la opción -c, (la “c
” significa “crear”):
- htpasswd registry.password username
A continuación, editará el archivo docker-compose.yml
para indicar a Docker que utilice el archivo que creó con el propósito de autenticar usuarios.
- cd ~/docker-registry
- nano docker-compose.yml
Puede añadir variables de entorno y un volumen para el directorio auth/
que creó editando el archivo docker-compose.yml
, para indicar a Docker la forma en que desea autenticar usuarios. Añada el siguiente contenido resaltado al archivo:
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
Para REGISTRY_AUTH
especificó htpasswd
, que es el esquema de autenticación que está usando, y fijó REGISTRY_AUTH_HTPASSWD_PATH
en la ruta del archivo de autenticación. Por último, REGISTRY_AUTH_HTPASSWD_REALM
es el nombre de dominio de htpasswd
.
Ahora puede verificar que su autenticación funcione correctamente ejecutando el registro y comprobando que solicite a los usuarios un nombre de usuario y una contraseña.
- docker-compose up
En una ventana del navegador, abra https://example.com/v2
.
Después de ingresar username
y la contraseña correspondiente, verá {}
una vez más. Con esto, confirmó la configuración básica de autenticación; el registro solo mostró el resultado después de que usted introducido el nombre de usuario y la contraseña correctos. De esta manera, protegió su registro y puede continuar usándolo.
Le convendrá asegurarse de que su registro se inicie siempre que el sistema se cargue. Si se produce un error imprevisto en el sistema, le convendrá asegurarse de que el registro se reinicie cuando el servidor lo haga. Abra docker-compose.yml
:
- nano docker-compose.yml
Añada la siguiente línea de contenido en registry
:
...
registry:
restart: always
...
Puede iniciar su registro como proceso en segundo plano, lo que le permitirá cerrar la sesión ssh
y persistir el proceso:
- docker-compose up -d
Con su registro ejecutándose en segundo plano, ahora podrá preparar Nginx para subir archivos.
Para poder introducir una imagen en el registro, deberá asegurarse de que este pueda gestionar cargas de archivos grandes. Aunque Docker divide las cargas de imágenes grandes en capas separadas, a veces pueden ocupar más de 1 GB
. Por defecto, Nginx tiene un límite de 1 MB
para las cargas de archivos, de modo que deberá editar el archivo de configuración para nginx
y fijar en 2 GB
el tamaño máximo para la carga de archivos.
- sudo nano /etc/nginx/nginx.conf
Busque la sección http
y añada la siguiente línea:
...
http {
client_max_body_size 2000M;
...
}
...
Finalmente, reinicie Nginx para aplicar los cambios en la configuración:
- sudo service nginx restart
Ahora puede subir imágenes grandes a su Docker Registry sin errores de Nginx.
Ahora estará listo para publicar una imagen en su Docker Registry privado, pero primero deberá crear una imagen. Para este tutorial, creará una imagen sencilla basada en la imagen de ubuntu
de Docker Hub. Docker Hub es un registro alojado públicamente, con muchas imágenes preconfiguradas que pueden utilizarse para “dockerizar” rápidamente aplicaciones. Usando la imagen de ubuntu
, probará la introducción en su registro y la y extracción de este.
Desde su servidor cliente, cree una imagen pequeña y vacía para la introducción en su nuevo registro; los indicadores -i
y -t
le proporcionan acceso de shell interactivo al contenedor:
- docker run -t -i ubuntu /bin/bash
Tras terminar la descarga, se posicionará dentro de una instrucción de Docker. Tenga en cuenta que el ID de su contenedor después de root@
variará. Realice un cambio rápido en el sistema de archivos creando un archivo llamado SUCCESS
. En el siguiente paso, podrá usar este archivo para determinar si el proceso de publicación se realiza correctamente:
- touch /SUCCESS
Cierre el contenedor de Docker:
- exit
Con el siguiente comando, se crea una nueva imagen llamada test-image
basada en la imagen que ya está en ejecución y se suma cualquier cambio que haya realizado. En nuestro caso, la adición del archivo /SUCCESS
se incluye en la nueva imagen.
Aplique el cambio:
- docker commit $(docker ps -lq) test-image
En este punto, la imagen solo existe a nivel local. Ahora podrá introducirla en el nuevo registro que creó. Inicie sesión en su Docker Registry:
- docker login https://example.com
Introduzca el username
y la contraseña correspondiente antes utilizados. A continuación, etiquetará la imagen con la ubicación del registro privado para introducirla en él:
- docker tag test-image example.com/test-image
Introduzca la imagen recién etiquetada en el registro:
- docker push example.com/test-image
El resultado debe tener un aspecto similar al siguiente:
OutputThe push refers to a repository [example.com/test-image]
e3fbbfb44187: Pushed
5f70bf18a086: Pushed
a3b5c80a4eba: Pushed
7f18b442972b: Pushed
3ce512daaf78: Pushed
7aae4540b42d: Pushed
...
Con esto, habrá verificado que su registro gestione la autenticación de usuarios y permita que los usuarios autenticados introduzcan imágenes en el registro. A continuación, confirmará que también puede extraer imágenes del registro.
Vuelva al servidor de su registro para poder probar la extracción de la imagen desde su servidor de cliente. También es posible probar esto desde un tercer servidor.
Inicie sesión con el nombre de usuario y la contraseña que estableció previamente:
- docker login https://example.com
Con esto, estará listo para extraer la imagen. Utilice el nombre de su dominio e imagen, que etiquetó en el paso previo:
- docker pull example.com/test-image
Docker descargará la imagen y lo conducirá a la línea de comandos. Si ejecuta la imagen en el servidor de registro, verá que el archivo SUCCESS
que creó antes estará allí:
- docker run -it example.com/test-image /bin/bash
Liste sus archivos dentro del shell de bash:
- ls
Verá el archivo SUCCESS
que creó para esta imagen:
SUCCESS bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
Con esto, habrá terminado de configurar un registro seguro en el cual los usuarios puedan introducir imágenes personalizadas y desde el cual pueden extraerlas.
A través de este tutorial, configuró su propio Docker Registry privado y publicó una imagen de Docker. Como se mencionó en la introducción, también puede usar TravisCI o una herramienta CI similar para automatizar la introducción directa en un registro privado. Al aprovechar Docker y los registros en su flujo de trabajo, puede garantizar que la imagen que contiene el código tendrá el mismo comportamiento en cualquier máquina, ya sea para la producción o el desarrollo. Para obtener más información sobre la escritura de archivos de Docker, puede leer este tutorial de Docker en el que se explica el proceso.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!