Una aplicación con Docker

Hoy la mayor parte de las aplicaciones que nos dan servicio a través de móviles o navegadores residen en la «nube», y en el fundamento de esta, de la «cloud», están los «contenedores». De lo que se trata es de poder manejar aplicaciones muy diferentes de la misma manera, el contenedor es un simil extraido de la manera en que se transportan mercancías de todo tipo por el mundo. Docker es probablemente la tecnología de contenedores mas difundida.

La clave del contenedor es la virtualización, que permite que quien gestiona la aplicación se desentienda de sus peculiaridades. La virtualización posibilita dos cosas:

  • Una gestión sencilla de aplicaciones en los servidores: desde el punto de vista del operador todas las aplicaciones son solo contenedores, sin importar la tecnología que haya dentro, todas se arrancan, se apagan y configuran de la misma manera.
  • Un despliegue de aplicaciones sin complicaciones: si funciona en tu ordenador, funcionará en el servidor; es el mundo DevOps.

Probablemente el éxito de los contenedores esté en que realizan una virtualización muy ligera. Cuando una aplicación se despliega en un contenedor no corre sobre una máquina virtual que incluye todo un sistema operativo. Un contenedor incluye la aplicación y tan solo las librerías de sistema que realmente necesita.

En esta entrada vamos a ver como crear una aplicacioncita, meterla en un contenedor y arrancarla. La aplicación de ejemplo usa tecnología Java y el sistema es Linux Ubuntu, pero la combinación podría ser cualquier otra.

Para empezar necesitamos Docker instalado en el equipo. Para instalar la Community Edition de Docker para Ubuntu (64 bits) se puede seguir lo indicado aquí.

Al terminar podemos probar que la instalación ha ido bien:
$ sudo docker run hello-world

pasted_image

Este comando trata de ejecutar una imagen de contenedor llamada “hello-world”. Como no la tiene se la descarga del repositorio por defecto y luego la ejecuta sobre el motor Docker. La aplicación muestra un saludo en texto.

Ahora vamos a crear la aplicación «misaludo». Creamos un directorio con la estructura típica de un programa Java:
$ mkdir -p misaludo/src/main/java/hola

Creamos un fichero pom.xml, el descriptor de este aplicativo. Como usamos Java nos valemos de Maven para construirlo, pero podría haber sido una aplicación Node usando NPM, o una PHP usando Composer… la tecnología del programa que corre dentro del contenedor puede ser cualquiera.

Abrimos un editor y creamos el pom.xml:
$ vim misaludo/pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>

<groupId>org.miorganizacion</groupId>
 <artifactId>mi-spring-boot-docker</artifactId>
 <version>0.1.0</version>

<parent>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-parent</artifactId>
 <version>1.5.2.RELEASE</version>
</parent>

<properties>
 <java.version>1.8</java.version>
</properties>

<dependencies>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-test</artifactId>
 <scope>test</scope>
 </dependency>
</dependencies>

<build>
 <plugins>
 <plugin>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-maven-plugin</artifactId>
 </plugin>
 </plugins>
</build>

</project>

Entre las dependencias de este ejemplo tenemos Spring Boot, un framework que permite construir programas que hacen muchas cosas con poco esfuerzo. «misaludo» será una aplicación web que devuelve el mensaje «¡Hola Docker!».

Ahora podemos crear la aplicación abriendo un editor y copiando el código que sigue a continuación:
$ vim misaludo/src/main/java/hola/Aplicacion.java

package hola;


import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;


@SpringBootApplication
 @RestController
 public class Aplicacion {


@RequestMapping("/")
 public String home() {
 return "¡Hola Docker!";
 }


public static void main(String[] args) {
 SpringApplication.run(Aplicacion.class, args);
 }
 }

Construimos a continuación el programa con Maven y lo probamos (hay que tener Maven y Java 8 instalado, si no lo tienes puedes seguir lo dicho aquí y aquí)
$ mvn package && java -jar target/mi-spring-boot-docker-0.1.0.jar

El programa levanta un servidor web Tomcat conteniendo nuestra aplicación. Si vamos al navegador y ponemos localhost:8080 veremos el saludo.

pasted_image002

Hemos creado y probado el programa. Ahora vamos a preparar su contenedor, lo construiremos y lo arrancaremos para comprobar que llegamos al mismo resultado.

Docker usa un fichero Dockerfile como descriptor del contenedor. Creamos el fichero Dockerfile:
$ vim misaludo/src/main/docker/Dockerfile

FROM frolvlad/alpine-oraclejdk8:slim
 VOLUME /tmp
 ADD mi-spring-boot-docker-0.1.0.jar app.jar
 RUN sh -c 'touch /app.jar'
 ENV JAVA_OPTS=""
 ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]

En Dockerfile se indica en ADD que ejecutable se añade al contenedor, y en la entrada ENTRYPOINT como ejecutarlo.

Para construir la imagen docker (el contenedor) podemos usar Maven. Se añade al pom.xml una propiedad indicando el prefijo que ayuda a identificar el contenedor, y un plugin de construcción que sabe como como crear imágenes.

<properties>
 [...]
 <docker.image.prefix>clublasindias</docker.image.prefix> </properties>


<build>
 <plugins>
 [...]
 <plugin>
 <groupId>com.spotify</groupId>
 <artifactId>docker-maven-plugin</artifactId>
 <version>0.4.9</version>
 <configuration>
 <imageName>${docker.image.prefix}/${project.artifactId}</imageName>
 <dockerDirectory>src/main/docker</dockerDirectory>
 <resources>
 <resource>
 <targetPath>/</targetPath>
 <directory>${project.build.directory}</directory>
 <include>${project.build.finalName}.jar</include>
 </resource>
 </resources>
 </configuration>
 </plugin>
 </plugins>
</build>

Antes de indicar a Maven que construya el contenedor necesitamos el motor Docker arrancado:
$ sudo service docker start

A partir de lo indicado en el pom.xml nuestro contenedor tendrá por nombre clublasindias/mi-spring-boot-docker. Para construirlo hacemos:
$ mvn package docker:build

Arrancamos el contenedor de la siguiente manera:
$ sudo docker run -p 8080:8080 -t clublasindias/mi-spring-boot-docker

Si ahora vamos en el navegador a localhost:8080 veremos el saludo «¡Hola Docker!» que ahora es ofrecido por el contenedor. ¡Aplausos! 🙂

Si hacemos sudo docker ps veremos la nueva imagen corriendo en el motor docker:

pasted_image003

 

Referencia: https://spring.io/guides/gs/spring-boot-docker/