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/

Mis datos en las nubes

A veces me sorprendo de hasta que punto nos hemos habituado a ceder nuestra información a otros incluso cuando no es necesario.

La razón por la que empecé a usar servicios como Google Reader o el panel de iGoogle era la misma por la que leía el correo electrónico por la web: poder acceder a esta info desde cualquier lado. Mi portátil no era precisamente móvil y con estos servicios, que todavía no sabían que estaban en un lugar llamado nube, podía trabajar de la misma manera desde cualquier sitio, usando un sencillo navegador y sin tener que instalar nada.

Hoy en día usamos todo tipo de servicios sin preguntarnos porqué tenemos que estar dando gratuitamente los datos acerca de nuestro trabajo, nuestros gustos, y nuestra actividad a empresas que en ocasiones solo piensan en explotarlos sin escrúpulos.

Seguro que no es el caso de esta empresa, pero da lo mismo: hace un par de semanas estaba pensando en cambiar mi aplicación de gestión de tareas en mi móvil, Gtasks, por Wunderlist (hay mucho bla, bla, bla sobre ella y quería probarla)… que rápido pasa uno de un servicio a otro… pero ¡vaya! ¿porqué lo hago si ahora las tareas ya viajan conmigo a todas partes en mi móvil? Para acceder a mi lista de tareas no necesito ningún servicio, la lista va conmigo a todas partes, ahora mi móvil es un portátil…

Pero no, hacemos uso del servicio, hacemos de beta-tester de la aplicación y nos tragamos todos los fallos de sincronización que sean necesarios :-). Hay servicios, como las redes sociales, para los que necesitamos de nube centralizada, pero es que ya no nos planteamos otra opción ni siquiera cuando existe.

Creo que la privacidad sigue siendo tan importante como siempre. Ser transparente y abierto no significa tener que perderla. Quizá deberíamos pensar donde nos estamos metiendo sobre todo cuando saltan noticias en plan Big Brother como en el caso de las revelaciones del señor Edward Snowden.