Par 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 :
- Comment l’image Docker a été construire
- 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 :
- une image Linux,
- une JVM Java 7 ou 8
- 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 :
- Docker container for the Spring Boot Petclinic application
- Starting Guide Spring Boot With Docker
- Image Docker officielle pour Java basée sur OpenJDK
- Documentation du plugin docker-maven-plugin
- Version Angular JS de l’application SpringBoot Petclinic
- Client Java pour Docker