1. Introducción

En este post veremos como crear un contenedor Docker a partir de un microservicio de SpringBoot.
Pueden encontrar el código fuente en mi GitHub.

Tecnologías empleadas:

  • Java 8
  • Gradle 3.1
  • SpringBoot 1.5.2.RELEASE
  • Docker 17.03.0-ce

2. ¿Qué es Docker?

De forma resumida Docker viene a ser un mecanismo de virtualización ligero en donde no existe sistema operativo en los contenedores que se ejecutan. De esta forma la distribución de software se torna mucho más ágil, sencilla y rápida que anteriormente ya que sólamente dispondremos de lo indispensable para que la operativa funcione correctamente. Por ejemplo, si queremos crear una imagen docker de un microservicio de SpringBoot, simplemente necesitaremos de un jdk instalada en nuestro contenedor y no de un sistema operativo entero.

En los mecanismos virtualización clásicos como VirtualBox o VMWare existe un sistema operativo instalado en la máquina virtual sobre la que corren las aplicaciones.

Sin embargo con este nuevo mecanismo de virtualización, es el motor Docker el encargado de abstraer a los contenedores el sistema operativo nativo.

3. Estructura del proyecto

3. Requisitos previos
Instalación de gradle
El proyecto ha sido montado sobre gradle, así que si no lo tienes instalado deberás.

  1. Descargar gradle de la web oficial
  2. Descomprimir los binarios en un directorio dentro de tu filesystem
  3. Importar el directorio /bin del gradle a la variable de entorno PATH

Para verificar que hemos configurado gradle correctamente deberemos hacer

gradle -v

Instalación de Docker
Deberás por otra parte tener instalado en tu PC Docker. Si no lo tienes instalado, descargar de la página oficial Docker. Para verificar que tienes instalado docker correctamente hacer en el terminal.

docker version

Crear cuenta en hub.docker.com
Es necesario que te crees una cuenta en hub.docker.com donde podrás almacenar tus imágenes docker en la nube, de tal forma que podrás ejecutar tus imagenes allá donde quieras.

4. Ficheros

A continuación se muestra el build.gradle. Para crear nuestra primera imagen Docker a partir de un microservicio de SpringBoot simplemente deberemos incluir la dependencia se.transmode.gradle:gradle-docker:1.2, el plugin docker y finalmente la tarea gradle que nos permita generar la imagen.

group 'com.jorgehernandezramirez.spring.springboot'
version '1.0-SNAPSHOT'

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.2.RELEASE")
        classpath('se.transmode.gradle:gradle-docker:1.2')
    }
}

apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'maven'
apply plugin: 'docker'

sourceCompatibility = 1.8

springBoot {
    mainClass = "com.jorgehernandezramirez.spring.springboot.docker.Application"
}

repositories {
    mavenCentral()
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web")
}

task buildDocker(type: Docker, dependsOn: build) {
    push = project.hasProperty('push')
    applicationName = jar.baseName
    tag = 'jorgehernandezramirez/spring-boot-docker'
    dockerfile = file('src/main/docker/Dockerfile')
    doFirst {
        copy {
            from jar
            into stageDir
        }
    }
}

La tarea buildDocker es la que nos va a crear nuestra imagen docker, la cual se encontrará tras la compilación en el directorio build/docker. Atributos a especificar

  • push. Indica si queremos subir la imagen docker a nuestro hub. Para ello habrá que realizar un login previo en docker (docker login) y autenticarnos con nuestras credenciales de hub.docker.com
  • applicationName. Nombre de la imagen Docker que se creará
  • tag. Nombre del repositorio en el hub de docker en donde subiremos nuestra imagen
  • dockerfile. Fichero en donde se indica la imagen base que se utilizará para crear nuestra imagen docker además de los pasos necesarios para arrancar nuestra imagen

Como vemos a continuación vamos a utilizar la imagen base frolvlad/alpine-oraclejdk8:latest para construir nuestra imagen de SpringBoot. Ésta contiene básicamente una jdk8 sobre la que arrancar nuestras aplicaciones Java. Podréis encontrar en store.docker.com el repositorio de imagenes disponibles.

FROM frolvlad/alpine-oraclejdk8:latest
VOLUME /tmp
ADD docker-1.0-SNAPSHOT.jar app.jar
RUN sh -c 'touch /app.jar'
ENTRYPOINT [ "sh", "-c", "java -jar /app.jar" ]

Main de SpringBoot

package com.jorgehernandezramirez.spring.springboot.docker;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

    public Application(){
        //For Spring
    }

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

Controlador de ejemplo

package com.jorgehernandezramirez.spring.springboot.docker.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloWorldController {

    @RequestMapping("/")
    public String doHelloWorld() {
        return "Hello World!";
    }
}

5. Creación y ejecución de imagen docker

En primer lugar, nos logamos en docker para poder subir nuestra imagen a nuestro repositorio en hub.docker.com.

docker login

A continuación creamos y subimos nuestra imagen docker a nuestro repositorio

gradle buildDocker -Ppush

Vemos como tenemos en nuestro repositorio nuestra nueva imagen.

Para descargarla y ejecutarla deberemos hacer

docker run -p8080:8080 jorgehernandezramirez/spring-boot-docker:1.0-SNAPSHOT

Para mayor aclaración lo que se está ejecutando dentro del contenedor es nuestro microservicio de SpringBoot que hemos construído anteriormente.

Accedemos al navegador a http://localhost:8080

6. Conclusiones

En este post hemos visto como crear una imagen Docker a partir de una microservicio de SpringBoot. La ventaja de crear y distribuir imágenes Docker es la capacidad de ejecutar nuestros ejemplos sin necesidad de tener instalado en el PC destino toda la infraestructura software necesaria, como gradle para compilar o la JVM para ejecutar.

Además, la gran potencia de Docker radica en que podemos encontrar imágenes de casi cualquier cosa que necesitemos, como RabbitMQ, Cassandra, MongoDB, ElasticSearch, elk… por lo que la distribución del software se hace mucho más sencilla.