Conteneurs: Application à Java

Containers
Docker
Java
I211
PO43
Lecture
Application des conteneurs pour la langage Java.
Auteur
Affiliations

Université de Toulon

LIS UMR CNRS 7020

Date de publication

2024-10-02

Source
Branch
  • develop (b23c847)
  • 2024-03-08 09:42:51
Java
  • OpenJDK Temurin-21.0.4+7
  • Apache Maven 3.9.9
Docker
  • Client: 27.2.0 - buildx v0.16.2 - compose v2.29.7
  • Server: 27.2.0

Cette partie illustre les différentes approches pour générer des images docker pour des applications Java.

A partir d’une image de maven

Le plus simple est de s’appuyer sur une image de maven, d’y copier les sources et de donner comme commande le résutat de compilation.

FROM maven:3.9.0-eclipse-temurin-17-focal

WORKDIR /app
COPY pom.xml ./
RUN mvn dependency:resolve
COPY src ./src

RUN mvn clean verify

CMD mvn --quiet exec:java -Dexec.mainClass="fr.univtln.bruno.demos.docker.App"
# CMD java -jar target/*-jar-with-dependencies.jar
# CMD java -cp target/*-jar-with-dependencies.jar fr.univtln.bruno.demos.docker.App
(cd sample-java/helloworld && \
docker image build --quiet --tag javahello:mavenimage --file Dockerfile.01.mavenimage . )
sha256:16887bfdedb5c897ff7ae559a4ecd64b83310fe8fa2e11961ce773145612ffec
docker image ls|grep javahello|grep "mavenimage "|tr -s ' '
javahello mavenimage 16887bfdedb5 Less than a second ago 573MB
docker run --rm javahello:mavenimage
04:47:52.512 [fr.univtln.bruno.demos.docker.App.main()] INFO fr.univtln.bruno.demos.docker.App - Hello world maven + docker.

Multistage

Il est plus efficace de s’appuyer sur la fabrication multistage d’une image docker pour séparer la chaîne de compilation de l’image d’exécution. On utilise alors comme image finale une base de JRE (donc plus légère) dans laquelle uniquement le résultat de la compilation est copié (attention, il doit inclure les dépendances cf. uberjar).

FROM maven:3.9.0-eclipse-temurin-17-focal as stage-build
WORKDIR /app
COPY pom.xml ./
RUN mvn dependency:resolve
COPY src ./src
RUN mvn clean verify

FROM eclipse-temurin:17-jre-jammy
COPY --from=stage-build /app/target/*-jar-with-dependencies.jar /myapp.jar
CMD ["java","-jar","/myapp.jar"]
(cd sample-java/helloworld && \
docker image build --quiet --tag javahello:mavenimagestage --file Dockerfile.02.mavenimagestage . )
sha256:ee4acfa81bd04ceb807dc42042ae77173b0cd8bccebdecb42e3482eff7550e04
docker image ls|grep javahello|grep mavenimagestage|tr -s ' '
javahello mavenimagestage ee4acfa81bd0 Less than a second ago 249MB
docker run --rm javahello:mavenimagestage
04:48:00.715 [main] INFO fr.univtln.bruno.demos.docker.App - Hello world maven + docker.

Cache docker

Les versions récentes de Docker proposent un mécanisme de cache qui permet de préciser explictement un dossier à mettre en cache lors du build d’une image. Pour Java et Maven, on peut ainsi mettre en cache ~/.m2 pour éviter de retélécharger systématiquement.

FROM maven:3.9.0-eclipse-temurin-17-focal as stage-build
WORKDIR /app
COPY . ./
RUN --mount=type=cache,target=/root/.m2 mvn clean verify

FROM eclipse-temurin:17-jre-jammy
COPY --from=stage-build /app/target/*-jar-with-dependencies.jar /myapp.jar
CMD ["java","-jar","/myapp.jar"]
(cd sample-java/helloworld && \
docker image build --quiet --tag javahello:cache --file Dockerfile.03.cache . )
sha256:4dd036700a92b691215f7ee9456c9c5ebebb8bb999486338a4195358d9e3da2e
docker image ls|grep javahello|grep cache|tr -s ' '
javahello cache 4dd036700a92 Less than a second ago 249MB
docker run --rm javahello:cache
04:48:21.222 [main] INFO fr.univtln.bruno.demos.docker.App - Hello world maven + docker.

Maven wrapper

Il est aussi possible de s’appuyer simplement sur l’image d’un JDK et d’utiliser un wrapper maven. Dans ce cas, la bonne version de maven sera téléchargée au moment de la compilation.

FROM eclipse-temurin:17-jdk-jammy as stage-build
WORKDIR /app
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
RUN ./mvnw dependency:resolve
COPY src ./src
RUN ./mvnw clean verify

FROM eclipse-temurin:17-jre-jammy
COPY --from=stage-build /app/target/*-jar-with-dependencies.jar /myapp.jar
CMD ["java","-jar","/myapp.jar"]
(cd sample-java/helloworld && \
docker image build --quiet --tag javahello:wrapper --file Dockerfile.04.wrapper . )
sha256:f865467f83e95aa2e39127112475128aa2182797b1078d25a037165e73eb5e68
docker image ls|grep javahello|grep wrapper|tr -s ' '
javahello wrapper f865467f83e9 Less than a second ago 249MB
docker run --rm javahello:wrapper
04:49:07.293 [main] INFO fr.univtln.bruno.demos.docker.App - Hello world maven + docker.

From scratch

Il est aussi possible réaliser une chaine de compilation personnalisée à partir de zéro par exemple avec sdkman.

FROM ubuntu:jammy as stage-build

ARG JAVA_VERSION="17.0.6-tem"
ARG MAVEN_VERSION="3.9.0"

RUN apt-get update && \
    apt-get install --yes --quiet --no-install-recommends ca-certificates curl zip unzip && \
    curl -s "https://get.sdkman.io" | bash

SHELL ["/bin/bash", "-c"]

RUN source $HOME/.sdkman/bin/sdkman-init.sh && \
    yes | sdk install java $JAVA_VERSION && \
    yes | sdk install maven $MAVEN_VERSION && \
    rm -rf $HOME/.sdkman/archives/* && \
    rm -rf $HOME/.sdkman/tmp/*

WORKDIR /app
COPY . ./
RUN --mount=type=cache,target=/root/.m2 source $HOME/.sdkman/bin/sdkman-init.sh && \
        mvn clean verify

FROM eclipse-temurin:17-jre-jammy
COPY --from=stage-build /app/target/*-jar-with-dependencies.jar /myapp.jar
CMD ["java","-jar","/myapp.jar"]
(cd sample-java/helloworld && \
docker image build --quiet --tag javahello:scratch --file Dockerfile.05.scratch . )
sha256:fb9e66c7f373395ba2742eda2a0c9df9112fb31fb2cb5c79a5050f21a7789a4c
docker image ls|grep javahello|grep scratch|tr -s ' '
javahello scratch fb9e66c7f373 1 second ago 249MB
docker run --rm javahello:scratch
04:49:56.456 [main] INFO fr.univtln.bruno.demos.docker.App - Hello world maven + docker.

Comparaison des images

docker image ls|grep javahello
javahello    scratch           fb9e66c7f373   1 second ago         249MB
javahello    wrapper           f865467f83e9   50 seconds ago       249MB
javahello    cache             4dd036700a92   About a minute ago   249MB
javahello    mavenimagestage   ee4acfa81bd0   About a minute ago   249MB
javahello    mavenimage        16887bfdedb5   2 minutes ago        573MB

Réutilisation