Docker

Trabajando con imágenes Docker

Cuando creamos nuestras propias imágenes (docker build, docker commit) podemos compartilas a través de registros como pueden llegar a ser Docker Hub[1], Quay[2], Amazon ECR[3], entre muchas otras opciones. Un registro es un repositorio donde se almacenan imágenes Docker para nuestro uso, por defecto es utilizado Docker Hub del cual podemos descargar (docker pull) imágenes oficiales de proyectos tan populares como Debian[4], MySQL[5], Apache[6], WordPress[7] entre muchos otros. El día de hoy vamos a ver no solamente cómo compartir nuestras imágenes Docker haciendo uso de registros sino también cómo se pueden compartir al exportarlas a un archivo .tar (docker save).

Sin importar que hayamos creado la imagen a través de un Dockerfile (docker build), haciendo un commit de los cambios de un contenedor actual o las imágenes base que encontramos en Docker Hub, podemos exportarlas a un archivo para compartila con otras personas. Por ejemplo, si a un contenedor que se instancia desde la imagen oficial de Debian le realizamos diferentes configuraciones, en el siguiente caso, la instalación del servidor web Apache:

$ docker run --it debian /bin/bash
# apt update
# apt -y install apache2

Luego podemos crear una nueva imagen partiendo del contenedor teniendo su container ID o nombre. A continuación se crea una nueva imagen llamada pabloxco/debian:v1 a partir del contenedor con el ID o nombre:

$ docker commit $CONTAINER_ID pabloxco/debian:v1

Con lo anterior, todos los contenedores que se instancien de dicha imagen tendrán las configuraciones previamente realizadas. Lo que podemos hacer ahora, es exportar la imagen a un archivo .tar con docker save:

$ docker save --output debian_apache.tar pabloxco/debian:v1

En este punto, ya podemos compartir la imagen y copiarla en algún otro host con Docker para realizar una carga de la imagen usando docker load. También podemos cargar imágenes en formato .tar.gz:

$ docker load --input debian_apache.tar

El flujo de trabajo anterior puede servir para pequeñas pruebas, pero en el largo plazo se puede volver un dolor de cabeza para el grupo de trabajo. Es aquí cuando entran en juego los registros Docker y como ya se decía inicialmente, son repositorios de imágenes que nos facilitan la tarea de compartirlas. Para hacer uso de un registro en concreto, debemos hacer login (docker login) para después poder descargar (docker pull) o subir (docker push) nuestras imágenes:

$ docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: pabloxco
Password:
Login Succeeded

Docker hub es el registro usado por defecto, si queremos hacer login en otros registros como por ejemplo Quay usaríamos docker login quay.io. Cuando realicemos login en uno o varios registros, los datos de inicio de sesión se almacenarán en $HOME/.docker/config.json:

{
"auths": {
"https://index.docker.io/v1/": {
"auth": "cGFibG94Y286Tm8sIGVuIHJlYWxpZGFkIG5vIHB1c2UgbWkgdmVyZGFkZXJvIHBhc3N3b3Jk"
}
}
}

Debemos tener cuidado con este archivo ya que el campo auth es en realidad un encode en base64 de los valores usuario:contraseña y se podría realizar un decode con base64 -d que fácilmente permite ver los datos en texto plano. Antes de subir (docker push) la imagen a Docker Hub a un repositorio que hayamos creado previamente desde la página[8] (que en este caso la llamaré debian), debemos ya sea renombrar (docker rename) o taggear (docker tag) la imagen para que el nombre tenga nuestro nombre de usuario del registro, nombre de la imagen (que sería el mismo del repositorio creado) y de manera opcional un tag de la siguiente manera: usuario_registro/nombre_imagen:tag. Como ya contamos con una imagen que cumple con este formato en el nombre, se puede realizar su subida a Docker Hub:

$ docker push pabloxco/debian:v1
The push refers to a repository [docker.io/pabloxco/debian]
bab7bf802aa5: Pushing [===> ] 4.314 MB/69.91 MB
fe4c16cbf7a4: Mounted from library/debian

Ahora, si por algún motivo estamos usando diferentes registros, la manera de reconocer a qué registro queremos enviar la imagen, es indicando el registro en el nombre de ésta última. Por ejemplo, si quisiéramos subir la imagen anterior a Quay nombraríamos o taggearíamos la imagen: quay.io/pabloxco/debian:v1 y luego procederíamos a realizar el docker push.

Uno de los puntos fuertes de implementar registros Docker en nuestro proceso de construcción y entrega de software es la integración con otro tipo de herramientas, como por ejemplo, sistemas de control de versiones. En Docker Hub podemos crear un repositorio de tipo Automated Build, el cual se debe linkear a un repositorio de Github o Bitbucket que estará pendiente de los commits realizados a los branches que creamos convenientes para la generación automática de la imágenes y de ésta manera tenerlas siempre actualizadas.

Por último, me gustaría mencionar que también podríamos implementar nuestro propio registro privado para almacenar nuestras imágenes Docker y como no podría ser de otra manera, el software necesario para cumplir éste propósito ya viene en forma de imagen Docker[9]:

$ docker run -p 5000:5000 registry

El anterior sería un registro para pruebas ya que para tener uno en producción se deberían tener en cuenta aspectos como la persistencia de datos del contenedor o la adición de certificados válidos al registro, pero ya son temas fuera del alcance de la presente entrada.