Dockerizando nuestros servicios

Dentro del entorno de DevOps, la tecnología de contenedores como Docker se ha extendido bastante debido a su facilidad de despliegue y portabilidad. En cuestión de pocos segundos podemos tener desplegado un entorno con uno o varios servicios, como un servidor web, una base de datos MySQL, etc.

La ventaja del uso de contenedores es que nos permite automatizar y desplegar aplicaciones de manera sencilla, teniendo todas las dependencias incluidas dentro del contenedor, lo que nos permite tener el mismo entorno en cualquier lugar donde lo despleguemos sin necesidad de tener más que Docker instalado en nuestro host y una imagen Docker que ejecutar.

Además, a diferencia de las máquinas virtuales, Docker no requiere un sistema operativo completo, sino que utiliza todas las funciones del sistema operativo de la máquina host, ahorrando espacio y ejecutándose mucho más rápido al no tener que levantar primero el sistema operativo como ocurre con las máquinas virtuales.

Ya hemos visto cómo podemos instalar Docker y Docker Compose en una máquina Ubuntu. En esta entrada queremos mostrar cómo podemos juntar esta tecnología con nuestro proyecto Spring Boot para desplegar de manera sencilla nuestra aplicación en cualquier máquina que tenga Docker instalado.

Docker se basa en el uso de un fichero Dockerfile donde podemos definir cómo se construye una imagen Docker. En el siguiente enlace se puede ver la documentación relacionada con la definición de este fichero: https://docs.docker.com/engine/reference/builder/

Nosotros vamos a utilizar un plugin de maven desarrollado por el equipo de Google Cloud: JIB (Java Image Builder). Este plugin nos va a permitir generar una imagen Docker de manera sencilla sin la necesidad de crear un fichero Dockerfile. Podemos ver la documentación de este plugin en su github: https://github.com/GoogleContainerTools/jib/tree/master/jib-maven-plugin.

Existen otras soluciones como Spotify/docker-maven-plugin o Fabric8, pero nosotros nos vamos a centrar en esta.

Lo primero que vamos a hacer es descargarnos nuestro proyecto Hello World! con Spring Boot e importarlo a Eclipse.

Una vez lo hemos añadido, abrimos el fichero pom.xml y añadimos el siguiente plugin:

<!-- Jib -->
<plugin>
            <groupId>com.google.cloud.tools</groupId>
            <artifactId>jib-maven-plugin</artifactId>
            <version>2.2.0</version>
            <configuration>
                <container>
                    <ports>
                          <port>8080</port>
                    </ports>
                    <creationTime>${maven.build.timestamp}</creationTime>
                </container>
                <from>
                    <image>openjdk:alpine</image>
                </from>
                <to>
                    <image>secdevoops/spring-boot-jib-docker:${project.version}</image>
                </to>
            </configuration>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>build</goal>
                    </goals>
                </execution>
            </executions>
</plugin>

Veamos en qué consiste la parte de configuración. Por un lado, vemos que tenemos la etiqueta <container>, dentro de la cual hemos definido el puerto 8080. Esto es como hacer un EXPOSE en nuestro fichero Dockerfile. Nos sirve para indicar al usuario que vaya usar la imagen cual es el puerto que estamos exponiendo. Dentro de la etiqueta container podemos definir otras propiedades del contenedor, como creationTime (si no lo indicamos, por defecto JIB utiliza Reproducible Builds que no incluye información del TIMESTAMP, con lo que la fecha de creación de la imagen será incorrecta), USER, el VOLUME, etc. En la documentación podemos ver todas las opciones.

Por otro lado, tenemos la etiqueta <from> donde indicamos la imagen base a partir de la cual construir nuestra propia imagen.

Finalmente, vemos que hemos indicado una etiqueta <to>, que indica el nombre de la imagen que le vamos a dar. También sirve para desplegar la imagen en un Docker Registry, que por defecto, si no indicamos lo contrario, es Docker Hub. Para poder desplegar, debemos añadir en nuestro fichero settings.xml de maven la siguiente configuración:

<servers>
    <server>
      <id>registry.hub.docker.com</id>
      <username>username</username>
      <password>password-docker-hub</password>
   </server>
</servers>

Por supuesto, si tenemos nuestro propio Docker Registry, indicaremos ahí los datos correctos. Nosotros no vamos a desplegar la imagen como desarrolladores, pero sí que se utilizará más adelante cuando configuremos un servidor de integración continua como Jenkins y hagamos el despliegue desde ahí.

Una vez que ya hemos añadido nuestro plugin y hemos añadido la configuración que necesitemos, ya podemos crear la imagen. Para esto, vamos a ejecutar el siguiente comando:

$ mvn compile jib:dockerBuild

Ahora, si miramos las imágenes de Docker que tenemos, veremos la nueva imagen creada.

Para levantar la imagen, no tenemos más que lanzar el siguiente comando, mapeando el puerto 8080 del contenedor con nuestro puerto 8081 (para ver la diferencia):

$ docker run -p 8081:8080 secdevoops/spring-boot-jib-docker:0.0.1-SNAPSHOT

Ahora ya tenemos nuestro contenedor levantado. Si accedemos a http://localhost:8080/hello (mediante curl o nuestro navegador) veremos la respuesta de nuestro servicio.

Podemos ver también qué contenedores están en ejecución con el comando $ docker ps

Por último, si quisiéramos desplegar nuestra imagen en Docker Hub (o nuestro propio Docker Registry) no tenemos más que ejecutar uno de los siguientes comandos:

$ mvn compile jib:build 
o 
$ mvn clean package

 

Categorías