viernes, 12 de octubre de 2018

Actualizando imágenes

Hola de nuevo, hoy vamos a ver un punto importante en el ciclo de vida de nuestras imágenes. Supongamos que tenemos una imagen de un servicio que dispone de actualizaciones automáticas o bien que queremos actualizar manualmente una imagen, pero no queremos bajar la última disponible de Docker Hub o reconstruir manualmente la imagen completa.

Para este ejemplo vamos a utilizar una imagen oficial de Jenkins descargada de Docker Hub. Para este caso, estableciendo el volumen donde vamos a mantener la configuración de Jenkins, al arrancar y configurar nuestro servicio Jenkins, nos encontramos con el siguiente mensaje al acceder al mismo:

Actualizaciones disponibles para Jenkins.
Como es lógico si nuestro contenedor es efímero, podemos descargar la actualización y trabajar con la versión actualizada pero, en cuanto paremos el contenedor habremos perdido la actualización y tendremos que realizarla de nuevo la próxima vez que arranquemos.

Ahora podríamos o bien bajar una imagen más moderna y usarla en todos nuestros contenedores o bien, podemos hacer uso del comando commit de docker, con el cual podemos crear una nueva imagen a partir del contenido de un contenedor. Veamos como hacerlo con nuestro Jenkins del ejemplo.

Realizamos la actualización de nuestro servicio Jenkins comenzando por los plugins que estemos utilizando:

Actualización de los plugins del servicio Jenkins.
En el caso de Jenkins hay que tener en cuenta que los plugins se almacenan en la carpeta de configuración, que deberíamos montar en un volumen para asegurar la persistencia de la configuración de nuestros jobs, usuarios, etc... Como ya vimos en otra entrada, podemos comprobar donde debemos montar nuestro volumen con solo usar el comando inspect sobre la imagen de jenkins:

Definición de volumen para servicio Jenkins.
Una vez actualizados los plugins vamos a pasar a actualizar el servicio Jenkins en si, para lo cual lo más sencillo es descargar el fichero de actualización y pasarlo a nuestro contenedor para sutituir el actual. De forma resumida sería algo como lo siguiente:

Paramos el servicio Jenkins dentro del contenedor.
Ahora copiamos el fichero de actualización de la nueva versión usando el comando docker cp:

Copiamos el fichero de actualización dentro del contenedor.
Ahora solo tenemos que copiar el fichero a la ruta correcta dentro del contenedor y pararlo.

Conectamos al contenedor y copiamos el fichero a la ruta correcta.
En este punto tenemos un contenedor parado a partir del cual podemos construir nuestra nueva imagen usando el comando commit de docker:

Creamos la nueva imagen a partir del contenedor parado.
Ahora solo tenemos que crear un contenedor, pero usando esta nueva imagen ya actualizada y conectarnos para comprobar que, efectivamente nuestro servicio está actualizado:

Creamos un contenedor usando nuestra nueva imagen de jenkins.

Nuestro servicio Jenkins ya actualizado.
En resumen, de una forma muy sencilla podremos crear imágenes a partir de contenedores en los que introduzcamos cambios de configuración o software. Esto nos permite mantener nuestros servicios actualizados y en el estado que nosotros queramos, ya que podemos controlar totalmente las imágenes que tengamos en nuestros repositorios.

El ejemplo que hemos visto es para un servicio Jenkins pero, como es evidente, es aplicable a practicamente cualquier otro y, como último punto a tener en cuenta, podemos usar la opción --pause con el comando commit si no queremos o no podemos parar el contenedor.