Image Docker pour Spring Boot Petclinic

docker-logoPar le passé, j’ai publié 2 images Docker sur le registre Docker Hub, l’équivalent du Maven Central Repository pour Docker : un client MySQL et une base PostgreSQL MusicBrainz. Ces images étaient construites puis publiées automatiquement à partir d’un dépôt GitHub contenant un Dockerfile et, éventuellement, un script Shell.

Plus récemment, j’ai souhaité mettre à disposition une image Docker de l’application Spring Petclinic basée sur Angular 1 et Spring Boot. Ce billet explique :

  1. Comment l’image Docker a été construire
  2. Et comment l’utiliser pour tester Petclinic

Automatisation de la construction

Pour utiliser le mécanisme de construction automatique proposé par Docker Hub, une 1ière solution aurait consisté à télécharger le JAR de Petclinic depuis un repo Maven public. Or, ce n’est pas (encore ?) le cas.
Une 2nde solution aurait été de faire construire le JAR par Docker. L’image aurait nécessité Git et Maven. Afin de garder une taille d’image raisonnable, le repo Maven local et le repo Git auraient dû être effacé après construction du JAR. Ce n’était pas la solution la plus optimale.

La solution que j’ai finalement retenue n’est pas basée sur le mécanisme proposé par Docker Hub mais sur l’utilisation du plugin pour Maven docker-maven-plugin développé par l’équipe de Spotify.

Configuration du docker-maven-plugin

Disponible sur la plateforme spring.io, le guide Starting Guide Spring Boot With Docker explique pas à pas comment créer une image Docker d’une application Spring Boot.

Sur Petclinic, la configuration du docker-maven-plugin a été adaptée afin de faciliter la publication de l’image sur Docker Hub.
Voici un extrait du pom.xml du module springboot-petclinic-server :

<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>0.4.13</version>
    <configuration>
        <imageName>${docker.image.prefix}/springboot-petclinic</imageName>
        <dockerDirectory>src/main/docker</dockerDirectory>
        <resources>
            <resource>
                <targetPath>/</targetPath>
                <directory>${project.build.directory}</directory>
                <include>${project.build.finalName}.jar</include>
            </resource>
        </resources>
        <forceTags>true</forceTags>
        <imageTags>
            <imageTag>${project.version}</imageTag>
            <imageTag>latest</imageTag>
        </imageTags>
        <useConfigFile>true</useConfigFile>
    </configuration>
</plugin>

Le plugin est configuré pour utiliser la version Maven pour tagger l’image Docker.

La balise useConfigFile précise au plugin d’aller rechercher les paramètres d’authentification au registre Docker dans le fichier de configuration Docker. Sur mon mac, ce fichier de configuration config.json se situe dans le répertoire  ~/.docker :

{
        "auths": {
                "https://index.docker.io/v1/": {
                        "auth": "xxxxxxxxxx=="
                }
        }
}

Enfin, La propriété docker.image.prefix pointe sur mon compte personnel Docker Hub :

<properties>
    <docker.image.prefix>arey</docker.image.prefix>
</properties>

Dockerfile

Pour des images simples, le plugin docker-maven-plugin permet de se passer complètement de Dockerfile : image de base, nom de l’image et point d’entrée sont directement configurés dans le pom.xml. Charge au plugin de générer le Dockerfile.

Pour Petclinic, l’usage d’un Dockerfile été préféré.  Facultatives, quelques directives spécifiques ont été ajoutées. Par ailleurs, l’utilisation d’un Dockerfile présente l’avantage de pouvoir être utilisé en dehors de Maven. La propriété dockerDirectory référence le répertoire contenant le Dockerfile.

Pour être opérationnelle, l’image Docker de SpringBoot Petclinic nécessite :

  1. une image Linux,
  2. une JVM Java 7 ou 8
  3. et le JAR de Spring Petclinic.

L’image Docker basée sur OpenJDK couvre les 2 premiers besoins. La version basée sur le projet Alpine Linux permet d’utiliser une image de base très réduite (environ 5 Mo).

Au final, voici le Dockerfile de SpringBoot Petclinic :

FROM openjdk:alpine
MAINTAINER Antoine Rey <antoine.rey@free.fr>
# Spring Boot application creates working directories for Tomcat by default
VOLUME /tmp
ADD petclinic.jar petclinic.jar
RUN sh -c 'touch /petclinic.jar'
# To reduce Tomcat startup time we added a system property pointing to "/dev/urandom" as a source of entropy.
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/petclinic.jar"]

Pointue, l’utilisation du répertoire /tmp, du touch et du urandom sont détaillées dans le Starting Guide Spring Boot With Docker. Je vous laisse vous y référer.

Construire l’image Docker

La construction de l’image Docker passer par une unique commande Maven :

mvn docker:build

Au préalable, il est nécessaire de démarrer Docker. Dans le cas contraire, vous obtiendrez un message d’erreur similaire :

[INFO] Building image arey/springboot-petclinic
nov. 04, 2016 8:47:21 AM org.apache.http.impl.execchain.RetryExec execute
INFOS: I/O exception (java.io.IOException) caught when processing request to {}->unix://localhost:80: No such file or directory
…
ERROR] Failed to execute goal com.spotify:docker-maven-plugin:0.4.13:build (default-cli) on project springboot-petclinic-server: Exception caught: java.util.concurrent.ExecutionException: com.spotify.docker.client.shaded.javax.ws.rs.ProcessingException: java.io.IOException: No such file or directory

Techniquement, le plugin maven dialogue avec Docker par l’intermédiaire d’un client Java Docker également développé par Spotify. Les échanges se font en REST / JSON.

Une fois la commande mvn docker:build  exécutée, les étapes de construction de l’image apparaissent dans les logs Maven :

[INFO] --- docker-maven-plugin:0.4.13:build (default-cli) @ springboot-petclinic-server ---
[INFO] Copying /Users/arey/dev/github/spring-petclinic /springboot-petclinic-server/target/petclinic.jar -> /Users/arey/dev/github/spring-petclinic/springboot-petclinic-server/target/docker/petclinic.jar
[INFO] Copying src/main/docker/Dockerfile -> /Users/arey/dev/ github/spring-petclinic /springboot-petclinic-server/target/docker/Dockerfile
[INFO] Building image arey/springboot-petclinic
Step 1 : FROM openjdk:alpine
 ---> f1da3c7976d0
Step 2 : MAINTAINER Antoine Rey <antoine.rey@free.fr>
 ---> Using cache
 ---> 321262ba62a5
Step 3 : VOLUME /tmp
 ---> Using cache
 ---> 7de28ccfef3f
Step 4 : ADD petclinic.jar petclinic.jar
 ---> 2af817fea936
Removing intermediate container 939a70038030
Step 5 : RUN sh -c 'touch /petclinic.jar'
 ---> Running in e90cff88f24c
 ---> e95aaed6515b
Removing intermediate container e90cff88f24c
Step 6 : ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -jar /petclinic.jar
 ---> Running in 7d03e1941841
 ---> 3b9b33ffb62b
Removing intermediate container 7d03e1941841
Successfully built 3b9b33ffb62b
[INFO] Built arey/springboot-petclinic
[INFO] Tagging arey/springboot-petclinic with 1.4.1
[INFO] Tagging arey/springboot-petclinic with latest

L’image Docker arey/springboot-petclinic est construite et est disponible localement.

Pour tester par vous-même la création de l’image Docker de Spring Boot Petclinic, exécuter les commandes suivantes :

git clone https://github.com/spring-projects/spring-petclinic
cd spring-petclinic
git checkout angularjs
mvn clean install
cd spring-petclinic-server
mvn docker:build

Publier l’image Docker

Publier l’image Docker construite avec Maven dans le registre public Docker Hub est enfantin. Après avoir paramétré la propriété docker.image.prefix du pom.xml et le fichier de configuration ~/.docker/config.json , exécuter la ligne de commande Maven suivante :

mvn docker:build -DpushImageTag

Démarrer Spring Boot Petclinic

Démarrer l’image Docker arey/springboot-petclinic disponible sur Docker Hub ou construite localement se fait en ligne de commande :

docker run -e "SPRING_PROFILES_ACTIVE=prod" -p 8080:8080 -t --name springboot-petclinic arey/springboot-petclinic

L’application web est alors disponible sur l’URL http://DOCKER_HOST:8080/

Le profile Spring de prod permet d’activer la mise en cache et le versionning des ressources statiques (cf. application-prod.properties).

Pour arrêter le conteneur, utiliser la commande :

docker stop springboot-petclinic

Conclusion

Le packaging d’une application Spring Boot sous forme d’image Docker peut entièrement être automatisé avec Maven (mais également avec Gradle). Publier ensuite cette image sur Docker Hub et tout Internaute pourra tester votre application sans avoir à installer le moindre outil (mis à part Docker).

Concernant Petclinic, la prochaine étape pourrait consister à déployer cette image sur un Cloud public. A suivre …

Ressources :

  1. Docker container for the Spring Boot Petclinic application
  2. Starting Guide Spring Boot With Docker
  3. Image Docker officielle pour Java basée sur OpenJDK
  4. Documentation du plugin docker-maven-plugin
  5. Version Angular JS de l’application SpringBoot Petclinic
  6. Client Java pour Docker

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.