[Édition définitive 2018] [conteneurisation Java 11] Après avoir réduit la taille de l'application Spring Boot à la limite, créez-la avec Jib et poussez-la vers ECR

Le monde est un boom des conteneurs sans précédent, et quand je suis allé à la conférence cette année, il n'y avait pas de jour où je n'ai pas entendu l'histoire des k8.

Dans de telles circonstances, Java a une empreinte importante et est incompatible avec Cloud Functions telles que Lambda, il a donc tendance à être évité de diverses manières. Même si nous utilisons Java régulièrement, tout le monde écrit du matériel Java dans notre Future Advent Calendar 2018. Je ne. .. ..

J'adore Java, Python, Ruby, Go et ES6, et je pense que je devrais utiliser la bonne personne au bon endroit, mais cette fois, j'écrirai un article qui repoussera Java la veille de Noël.

JDK Warring States Era - Quel JDK devrions-nous utiliser?

Le monde a été précipité par le fait que Java, qui a été utilisé gratuitement par Oracle de Sun Microsystems, sera finalement facturé à partir de Java 11 en septembre 2018.

Cependant, si vous organisez correctement les informations, en plus du JDK Oracle pris en charge par Oracle moyennant des frais, la communauté et les fournisseurs publieront des versions LTS du JDK basées sur le JDK ouvert dirigé par Oracle, ce n'est donc pas un problème. Je pense.

Mais dans le monde de l'entreprise, qui est responsable des correctifs en temps opportun lorsque des vulnérabilités sont découvertes? Cependant, le fait est que la sécurité est basée sur une défense à plusieurs niveaux et que les vulnérabilités telles que les bibliothèques et les frameworks tels que Struts ont un impact plus important que Java lui-même, donc un état d'esprit purement japonais est un jugement normal. Je pense que c'est gênant, mais je pense que le support payant d'Oracle est également utile pour ces entreprises.

JDK Java8 Java11 Payant / gratuit Avec LTS commentaire
OracleJDK Payé Grandes entreprises, si vous voulez acheter la tranquillité d'esprit, ce
Oracle OpenJDK Gratuit Pas de version LTS, non utilisé avec Empra
Redhat OpenJDK Payé * Choix si vous utilisez Redhat
AdoptOpenJDK Gratuit Pour le moment, il peut être utilisé gratuitement et la communauté est solide, donc il est influent
Amazon Corretto Gratuit Il y a un sentiment de favori car il est développé par le père de Java, Gothrin sur AWS. Sortie de Java 11 attendue
GraalVM ✗ Gratuit Polyglot VM développé par Oracle. Cela semble explosif s'il est transformé en une image native, mais il existe de nombreuses restrictions

En outre, Amazon / Azure fournit également OpenJDK et prend en charge LTS, qui correspond exactement à l'ère des États en guerre.

C'est ironique car il est peu probable que cela se produise avec d'autres environnements d'exécution de langage, mais vous pouvez voir combien de systèmes Java sont utilisés ^^;

De plus, l'existence de Graal VM ne peut être négligée. Comme il existe diverses restrictions telles que le fait de ne pas encore pouvoir prendre en charge le chargement dynamique dans l'imagerie native, il ne peut pas être utilisé avec Spring Boot, etc., mais cela semble être une question de temps, je dois donc l'attendre avec impatience.

référence

Comparaison des fournisseurs de support commercial à long terme (LTS) pour JDK (également mentionnés pour une utilisation gratuite) --Qiita https://qiita.com/u-tanick/items/bb166929a58a4c20bb88

J'ai essayé GraalVM-Qiita https://qiita.com/sonodar/items/dcfafdfba8af2db53b16

Essayez de créer une image native de l'application Spring Boot avec Micronaut for Spring - Qiita https://qiita.com/h-r-k-matsumoto/items/5b82177294cd71df5024

La conteneurisation Java11 SpringBoot - La réduction de la taille n'est pas limitée à l'hôte -

À partir de là, pensons à exécuter sur Java 11 tout en utilisant l'application Web de SpringBoot comme sujet.

Si vous ne voulez pas en faire un conteneur, vous pouvez utiliser un seul Jar de démarrage (fat-jar) et ce sera très facile car vous pouvez simplement le déployer dans l'environnement où le JDK est installé. Je pense qu'il existe de nombreux cas où la taille du pot n'est que de quelques dizaines de Mo.

En ce qui concerne la conteneurisation, il est possible de copier le fichier jar ci-dessus dans l'image du conteneur contenant le JDK et de le démarrer, mais le problème ici est la taille de l'image. Le conteneur est petit mais juste, y compris PUSH / PULL dans le registre et le démarrage du conteneur lui-même.

OpenJDK (officiel)

Comme l'image dokcer (1 Go) d'OpenJDK11 est grande, créez une petite image (85 Mo) avec alpine linux + jlink --Qiita https://qiita.com/h-r-k-matsumoto/items/294eeb838cfd062d75b6

Comme présenté ici, l'image officielle d'OpenJDK est de 1 Go. De plus, il n'y a pas de LTS ... donc c'est hors des options.  Distroless by Google

Créer une image Docker d'exécution en utilisant une image sans distrol-Qiita https://qiita.com/some-nyan/items/90b624b0f148231748f0)

J'ai enquêté sur le fait que Distoless, qui est publié en tant qu'image pour l'exécution par Google, semble être bon, mais pour le moment, il ne prend en charge que Java 8 et il semble que je doive attendre le support de Java 11.

AdoptOpenJDK

En regardant adoptopenjdk / openjdk11: alpine publié par AdoptOpenJDK, il fait environ 200 Mo, ce qui est assez mince, alors utilisez ceci Il semble que partir soit une meilleure option à partir de 2018.

Cependant, si vous mettez une application dessus, elle sera plus lourde, donc comme indiqué dans l'article ci-dessus, Java 11 a également l'avantage du système de modules, nous allons donc créer un JRE personnalisé en utilisant jlink et le réduire davantage.

Par conséquent, le flux consiste d'abord à créer un JDK qui est réduit au minimum nécessaire pour faire fonctionner Spring Boot avec l'image Alpine d'AdoptOpenJDK, puis à le copier dans l'image d'origine d'Alpine.

La mise en garde ici est que la simple copie d'un JRE personnalisé dans une Alpine simple ne fonctionnera pas. Par conséquent, ajoutez la glibc comme indiqué ci-dessous.

Dockerfile


###########################################################
# spring-boot-jre-min-11
# Custom JRE from AdobtOpenJDK11 for spring-boot
# 
###########################################################
FROM adoptopenjdk/openjdk11:alpine AS builder

# create custom jre
RUN jlink \
    --module-path="${JAVA_HOME}/jmods" \
    --compress=2 \
    --add-modules=java.base,java.logging,java.xml,jdk.unsupported,java.sql,java.naming,java.desktop,java.management,java.security.jgss,java.instrument,jdk.charsets \
    --no-header-files \
    --no-man-pages \
    --verbose \
    --output=/opt/jre-min

# pull plane alpine
FROM alpine:3.8

ENV JAVA_HOME="/opt/jre-min"
ENV PATH="$PATH:/opt/jre-min/bin"
ENV JAVA_VERSION="jdk-11.0.1+13"
ENV JAVA_TOOL_OPTIONS="-XX:+UseContainerSupport"

# add glibc-compat
RUN apk --update add --no-cache ca-certificates curl openssl binutils xz \
    && GLIBC_VER="2.28-r0" \
    && ALPINE_GLIBC_REPO="https://github.com/sgerrand/alpine-pkg-glibc/releases/download" \
    && GCC_LIBS_URL="https://archive.archlinux.org/packages/g/gcc-libs/gcc-libs-8.2.1%2B20180831-1-x86_64.pkg.tar.xz" \
    && GCC_LIBS_SHA256=e4b39fb1f5957c5aab5c2ce0c46e03d30426f3b94b9992b009d417ff2d56af4d \
    && ZLIB_URL="https://archive.archlinux.org/packages/z/zlib/zlib-1%3A1.2.9-1-x86_64.pkg.tar.xz" \
    && ZLIB_SHA256=bb0959c08c1735de27abf01440a6f8a17c5c51e61c3b4c707e988c906d3b7f67 \
    && curl -Ls https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub -o /etc/apk/keys/sgerrand.rsa.pub \
    && curl -Ls ${ALPINE_GLIBC_REPO}/${GLIBC_VER}/glibc-${GLIBC_VER}.apk > /tmp/${GLIBC_VER}.apk \
    && apk add /tmp/${GLIBC_VER}.apk \
    && curl -Ls ${GCC_LIBS_URL} -o /tmp/gcc-libs.tar.xz \
    && echo "${GCC_LIBS_SHA256}  /tmp/gcc-libs.tar.xz" | sha256sum -c - \
    && mkdir /tmp/gcc \
    && tar -xf /tmp/gcc-libs.tar.xz -C /tmp/gcc \
    && mv /tmp/gcc/usr/lib/libgcc* /tmp/gcc/usr/lib/libstdc++* /usr/glibc-compat/lib \
    && strip /usr/glibc-compat/lib/libgcc_s.so.* /usr/glibc-compat/lib/libstdc++.so* \
    && curl -Ls ${ZLIB_URL} -o /tmp/libz.tar.xz \
    && echo "${ZLIB_SHA256}  /tmp/libz.tar.xz" | sha256sum -c - \
    && mkdir /tmp/libz \
    && tar -xf /tmp/libz.tar.xz -C /tmp/libz \
    && mv /tmp/libz/usr/lib/libz.so* /usr/glibc-compat/lib \
    && apk del binutils \
    && rm -rf /tmp/${GLIBC_VER}.apk /tmp/gcc /tmp/gcc-libs.tar.xz /tmp/libz /tmp/libz.tar.xz /var/cache/apk/*

COPY --from=builder /opt/jre-min /opt/jre-min

Voici ce que j'ai poussé vers Docker Hub.

shoutstar/spring-boot-jre-min-11 - Docker Hub https://hub.docker.com/r/shoutstar/spring-boot-jre-min-11

J'ai réussi à réduire la taille à 48 Mo: sourire:

Conteneurisé à la construction ~ Connaissez-vous Jib? ~

GoogleContainerTools/jib: Build container images for your Java applications. https://github.com/GoogleContainerTools/jib

Jib est un outil qui transforme une application Java publiée par Google sur OSS en juillet de cette année en une image de conteneur lors de la construction de Maven / Gradle et même l'enregistre dans le registre. Ce qui suit est détaillé.

"Jib" qui construit automatiquement des applications Java dans des images Docker, publié en open source par Google-Publickey https://www.publickey1.jp/blog/18/javadockerjibgoogle.html

Jib fournit un mécanisme pour pousser automatiquement non seulement DockerHub, mais également GCP GCR et AWS ECR. Il est extrêmement chaud qu'il puisse être automatisé jusqu'à présent sans écrire un Dockerfile et sans taper une commande docker: fire:.

Eh bien, comme j'ai écrit le Dockerfile plus tôt ... En fait, il y a une raison à cela. Dans Jib, l'image from est spécifiée dans les paramètres, mais il n'est pas possible de la personnaliser à partir de l'image en exécutant le jlink ci-dessus. Donc, si vous souhaitez l'exécuter avec jlink à l'aide d'un JRE personnalisé, vous devez créer une image de base à l'avance et la publier dans le registre.

https://github.com/GoogleContainerTools/jib/blob/master/docs/faq.md#i-need-to-run-commands-like-apt-get

Bien sûr, les ressources du chemin de classe sont automatiquement copiées, mais il est possible de copier tout fichier qui ne se trouve pas dans le chemin de classe en définissant.

https://github.com/GoogleContainerTools/jib/blob/master/docs/faq.md#i-need-to-run-commands-like-apt-get

En plus de PUSH dans le registre, Jib prend en charge l'enregistrement avec le démon Docker local, la création de tars, etc.

#PUSH au registre
$ mvn compile jib:build

#Inscription au démon Docker local (nécessite le démarrage de Docker)
$ mvn compile jib:dockerBuild

#Créer du tar
$ mvn compile jib:buildTar

Ensuite, cette fois, je vais passer à ECR avec le plug-in Maven de Jib.

pom.xml


<plugin>
    <groupId>com.google.cloud.tools</groupId>
    <artifactId>jib-maven-plugin</artifactId>
    <version>0.10.0</version>
    <configuration>
        <!--Dans certains cas, il est pratique de le mettre lors de l'utilisation d'un proxy-->
        <allowInsecureRegistries>true</allowInsecureRegistries>
        <from>
            <!--PULL une image légère avec uniquement un JRE personnalisé de Docker Hub-->
            <image>shoutstar/spring-boot-jre-min-11</image>
        </from>
        <to>
            <!--Au moment de la construction-Djib.to.Remplacer par l'image-->
            <image>future/sprinb-boot-app</image>
            <!--Au moment de la construction-Djib.to.Remplacer par credHelpr
            <credHelper>ecr-login</credHelper>
            -->
        </to>
        <container>
            <!--Je vais passer le profil du printemps ici-->
            <jvmFlags>
                <jvmFlag>-Dadd-opens=java.base/java.lang=ALL-UNNAMED</jvmFlag>
                <jvmFlag>-Dadd-opens=java.base/java.lang.invoke=ALL-UNNAMED</jvmFlag>
                <jvmFlag>-Dspring.profiles.active=${spring.profiles.active}</jvmFlag>
            </jvmFlags>
            <!--Définir l'heure de création de l'image au moment de la construction-->
            <useCurrentTimestamp>true</useCurrentTimestamp>
        </container>
    </configuration>
</plugin>

Supplément à pom.xml

jib.from.image

Le JRE personnalisé mentionné ci-dessus est spécifié. Il s'agit de shoutstar / spring-boot-jre-min-11 de Docker Hub.

jib.to.image, jib.to.credHelpr

Puisqu'il y a des cas où vous voulez le placer dans le Docker local pendant le développement, en gros, je pense qu'il est préférable de le remplacer par -Djib.to.image et -Djib.to.credHelper au moment de la construction.

PUSH à ECR

À l'origine, la commande $ (aws ecr get-login --no-include-email --region ap-north-1) est utilisée pour émettre la commande de connexion docker pour vous connecter, puis pousser. Vous pouvez le pousser en coopération avec l'outil de ligne de commande.

awslabs/amazon-ecr-credential-helper: Automatically gets credentials for Amazon ECR on docker push/docker pull https://github.com/awslabs/amazon-ecr-credential-helper

Suivez le README ci-dessus pour installer. L'installation de golang 1.6 ou supérieur est requise.

$ go get -u github.com/awslabs/amazon-ecr-credential-helper/ecr-login/cli/docker-credential-ecr-login

Mettez un lien symbolique dans $ GOPATH / bin / docker-credential-ecr-login et placez-le dans votre PATH.

Créez ensuite le fichier config.json suivant pour que toutes les connexions au registre ECR soient correctes.

json:~/.docker/config.json


{
    "credsStore": "ecr-login"
}

Si l'environnement de génération est EC2, si vous attribuez un rôle IAM, aucun autre paramètre n'est requis. Si ce n'est pas possible, définissez le secret de la clé d'accès dans ~ / .aws / credentials ou spécifiez ʻAWS_ACCESS_KEY_ID et ʻAWS_SECRET_ACCESS_KEY dans les variables d'environnement, respectivement.

Lorsque vous appuyez sur ECR, la commande est la suivante.

$ mvn clean compile jib:build \
-Djib.to.image=xxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/future/spring-boot-app \
-Djib.to.credHelper=ecr-login

...Omission

[INFO] --- jib-maven-plugin:0.10.0:build (default-cli) @ spring-boot-app ---
[WARNING] Setting image creation time to current time; your image may not be reproducible.
[INFO] 
[INFO] Containerizing application to xxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/future/spring-boot-app ...
[WARNING] Base image 'shoutstar/spring-boot-jre-min-11' does not use a specific image digest - build may not be reproducible
[INFO] Retrieving registry credentials for xxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com...
[INFO] Getting base image shoutstar/spring-boot-jre-min-11...
[INFO] Building snapshot dependencies layer...
[INFO] Building resources layer...
[INFO] Building dependencies layer...
[INFO] Building classes layer...
[INFO] The base image requires auth. Trying again for shoutstar/spring-boot-jre-min-11...
[INFO] Retrieving registry credentials for registry.hub.docker.com...
[INFO] 
[INFO] Container entrypoint set to [java, -Dadd-opens=java.base/java.lang=ALL-UNNAMED, -Dadd-opens=java.base/java.lang.invoke=ALL-UNNAMED, -Dspring.profiles.active=container, -cp, /app/resources:/app/classes:/app/libs/*, jp.co.future.sample.SpringBootApplication]
[INFO] Finalizing...
[INFO] 
[INFO] Built and pushed image as xxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/future/spring-boot-app
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

J'ai pu pousser vers ECR en toute sécurité.

À propos, c'est une application comme le clone spring-petclinic que j'ai créé pour vérifier le fonctionnement du framework interne, et la taille de l'image est d'environ 95 Mo. Fin 2018, je me demande si c'est la limite: sweat_smile:

À la fin

Jib a rendu les conteneurs familiers et faciles pour les ingénieurs Java, donc si vous ne les avez pas encore touchés, essayez-le. Après tout, j'ai utilisé la commande docker par essais et erreurs, donc je ne pense pas qu'elle puisse être utilisée par les utilisateurs Java qui ne connaissent pas Docker. .. ..

À l'avenir, si la vitesse de démarrage devient plus rapide avec GraalVM, il semble qu'il puisse être utilisé avec Cloud Function, et Micronaut, qui s'inspire de Spring Boot mais a une forte affinité avec GraalVM, est également à noter.

Il y a quelques jours à peine, Amazon EKS est arrivé dans la région de Tokyo, alors j'aimerais écrire sur le déploiement de l'image poussée vers ECR vers EKS.

Amazon EKS prend désormais en charge la région de Tokyo. | Blog Amazon Web Services https://aws.amazon.com/jp/blogs/news/amazon-eks-tokyo-region/

Recommended Posts

[Édition définitive 2018] [conteneurisation Java 11] Après avoir réduit la taille de l'application Spring Boot à la limite, créez-la avec Jib et poussez-la vers ECR
[Java] Déployer l'application Spring Boot sur Azure App Service
Transformez facilement les applications Java en conteneurs Docker avec Jib ~ Construisez avec gradle et enregistrez-vous dans le référentiel local
[Java] Article pour ajouter une validation avec Spring Boot 2.3.1.
Jusqu'à ce que vous créiez un projet Spring Boot dans Intellij et que vous le transmettiez à Github
Tentative de SSR Vue.js avec Spring Boot et GraalJS
Gérez l'API de date et d'heure Java 8 avec Thymeleaf avec Spring Boot
Implémenter l'API REST avec Spring Boot et JPA (Application Layer)
Déployez l'application créée par Spring Boot sur Heroku (public) ②
Jusqu'à INSERT et SELECT sur Postgres avec botte de printemps et feuille de thym
Comment appeler et utiliser l'API en Java (Spring Boot)
Déployez l'application créée par Spring Boot sur Heroku (public) ①
Connectez-vous à la base de données avec spring boot + spring jpa et effectuez l'opération CRUD
Développement piloté par domaine avec Java et Spring Boot-Layer et division de modules
[Spring Boot] Je veux ajouter mon propre fichier de propriétés et obtenir la valeur avec env.getProperty ().