Création d'un environnement Java léger qui s'exécute sur Docker

Basé sur Java in a World of Containers donné en japonais lors de la tournée Oracle Groundbreakers APAC à Tokyo le 11/13 J'écris.

introduction

La figure ci-dessous est un graphique de module de java9 ou version ultérieure. DD_IQdaVoAAc6Pu.jpg

Lors de l'écriture d'une application en Java, il est rare de tout utiliser dans ce graphe de module. Par exemple, java.xml, corba, javaws sont souvent inutiles.

Si vous créez une image Docker avec Linux et JDK sans y penser avec Docker, elle sera assez volumineuse. Par conséquent, il semble que les conteneurs et java soient souvent considérés comme incompatibles. Grande capacité, lourd, démarrage lent, etc. Pourtant, les fonctionnalités de Java sont également idéales pour les conteneurs. Il existe de nombreux avantages tels que l'autonomie d'exécution, le matériel et le système d'exploitation, la compatibilité de sécurité garantie par JVM, une exécution stable garantie lorsque l'environnement change, l'écosystème et le meilleur choix de conteneurs. .. Un JDK qui est trop lourd par défaut peut être amélioré en modularisant le JDK lui-même avec Jigsaw et en organisant les dépendances.

Dockerfile

Le système d'exploitation crée une image avec ubuntu: latest. Tout d'abord, créez un environnement avec la taille par défaut et essayez Hello World.

Dockerfile


FROM ubuntu:latest
ADD openjdk-11.0.1_linux-x64_bin.tar.gz /opt/jdk/
ADD HelloWorld.class HelloWorld.class
ENV PATH /opt/jdk/jdk-11.0.1/bin:$PATH
CMD [ "java", "-showversion", "HelloWorld" ]

Créez et exécutez l'image.

$ docker build -t helloworld-java .
$ docker run --rm helloworld-java
openjdk version "11.0.1" 2018-10-16
OpenJDK Runtime Environment 18.9 (build 11.0.1+13)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.1+13, mixed mode)
Hello World!

Jetons un coup d'œil à l'image créée.

$ docker images helloworld-java
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
helloworld-java     latest              682ae9922b5b        2 minutes ago       396MB

Il y a environ 400 Mo.

JRE personnalisé

Créez un JRE personnalisé à l'aide de jdeps et jlink. Vous pouvez voir les dépendances du module en utilisant jdeps. Jetons un coup d'œil au module Hello World.

$ jdeps --list-deps HelloWorld.class
   java.base

Le contenu étant Hello World, il existe peu de dépendances. Au niveau HelloWorld, il semble que seul le module java.base soit utilisé.

Créons un JRE personnalisé avec jlink.

 jlink --compress=2 --module-path $JAVA_HOME/jmods --add-modules java.base --output jre-min

Seul java.base est utilisé, donc add-modules seul est spécifié. Après l'exécution, jre-min est créé. Dans cet environnement, Hello World est le minimum requis pour s'exécuter. La capacité était également de 27 Mo.

python


.
├── Dockerfile
├── HelloWorld.class
├── HelloWorld.java
├── hello.jar
├── jre-min
│   ├── bin
│   │   ├── java
│   │   └── keytool
│   ├── conf
│   │   ├── net.properties
│   │   └── security
│   │       ├── java.policy
│   │       ├── java.security
│   │       └── policy
│   │           ├── README.txt
│   │           ├── limited
│   │           │   ├── default_US_export.policy
│   │           │   ├── default_local.policy
│   │           │   └── exempt_local.policy
│   │           └── unlimited
│   │               ├── default_US_export.policy
│   │               └── default_local.policy
│   ├── include
│   │   ├── classfile_constants.h
│   │   ├── darwin
│   │   │   └── jni_md.h
│   │   ├── jni.h
│   │   ├── jvmti.h
│   │   └── jvmticmlr.h
│   ├── legal
│   │   └── java.base
│   │       ├── COPYRIGHT
│   │       ├── LICENSE
│   │       ├── aes.md
│   │       ├── asm.md
│   │       ├── c-libutl.md
│   │       ├── cldr.md
│   │       ├── icu.md
│   │       ├── public_suffix.md
│   │       └── unicode.md
│   ├── lib
│   │   ├── classlist
│   │   ├── jli
│   │   │   └── libjli.dylib
│   │   ├── jrt-fs.jar
│   │   ├── jspawnhelper
│   │   ├── jvm.cfg
│   │   ├── libjava.dylib
│   │   ├── libjimage.dylib
│   │   ├── libjsig.dylib
│   │   ├── libnet.dylib
│   │   ├── libnio.dylib
│   │   ├── libosxsecurity.dylib
│   │   ├── libverify.dylib
│   │   ├── libzip.dylib
│   │   ├── modules
│   │   ├── security
│   │   │   ├── blacklisted.certs
│   │   │   ├── cacerts
│   │   │   ├── default.policy
│   │   │   └── public_suffix_list.dat
│   │   ├── server
│   │   │   ├── Xusage.txt
│   │   │   ├── libjsig.dylib
│   │   │   └── libjvm.dylib
│   │   └── tzdb.dat
│   └── release
└── openjdk-11.0.1_linux-x64_bin.tar.gz

Lançons Hello World dans cet environnement minimal.

$ jre-min/bin/java -showversion HelloWorld
java version "11.0.1" 2018-10-16 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.1+13-LTS)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.1+13-LTS, mixed mode)
Hello World!

Construction de Docker avec Java minimal

Créons un JRE personnalisé avec jlink et construisons-le.

Dockerfile


FROM ubuntu:latest AS build
ADD openjdk-11.0.1_linux-x64_bin.tar.gz /opt/jdk/
ENV PATH /opt/jdk/jdk-11.0.1/bin:$PATH
RUN ["jlink", "--compress=2", "--module-path", "/opt/jdk/jdk-11/jmods", "--add-modules", "java.base", "--output", "/linked"]

FROM ubuntu:latest
COPY --from=build /linked /opt/jdk/
ENV PATH=$PATH:/opt/jdk/bin
ADD HelloWorld.class /

CMD [ "java", "-showversion", "HelloWorld" ]
$ docker images
REPOSITORY        TAG        IMAGE ID            CREATED             SIZE
helloworld-java   latest     e71329542c40        2 minutes ago       123MB
$ docker run -it helloworld-java
openjdk version "11.0.1" 2018-10-16
OpenJDK Runtime Environment 18.9 (build 11.0.1+13)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.1+13, mixed mode)
Hello World!

La taille est inférieure au quart de la précédente.

Construction de l'environnement plus léger Construction de Docker

Nous avons le Java minimum requis, mais nous avons toujours 123 Mo. Si seule la méthode est utilisée plus tôt, seul Java peut être allégé, nous allons donc également modifier le système d'exploitation. Si vous voulez simplement exécuter ava, ubuntu est trop luxueux. Par conséquent, utilisez alpine linux pour créer l'environnement Linux minimum requis. alpine est un Linux léger basé sur musl libc et BusyBox (il ne contient vraiment rien ...). La configuration minimale semble être plus légère que 5 Mo. Reportez-vous à Dockerfile de l'environnement Java basé sur les Alpes publié par AdoptOpenJDK Créez une image avec la configuration minimale.

Dockerfile


FROM adoptopenjdk/openjdk11:alpine-slim AS jlink
RUN ["jlink", "--compress=2", \
     "--module-path", "/opt/java/openjdk/jmods", \
     "--add-modules", "java.base", \
     "--output", "/jlinked"]


FROM alpine

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=jlink /jlinked /opt/jdk/

ADD HelloWorld.class /
CMD ["/opt/jdk/bin/java", "-showversion", "HelloWorld"]
$ docker build -t helloworld-java .
$ docker images
REPOSITORY                TAG                 IMAGE ID            CREATED              SIZE
helloworld-java           latest              407614883e2b        38 seconds ago       52.1MB

C'est moins de la moitié du précédent. C'est environ 1/8 de l'original.

Bien sûr, il peut être exécuté

$ docker run -it helloworld-java
openjdk version "11.0.1" 2018-10-16
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.1+13)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.1+13, mixed mode)
Hello World!

Résumé

Il semble que l'on dise souvent que le conteneur et le java sont incompatibles l'un avec l'autre en raison de leur grande capacité, de leur poids élevé et de leur démarrage lent. Après JDK9, vous pouvez créer un environnement dédié avec jdeps et jlink. Puisqu'il est possible de créer l'environnement minimum nécessaire, il est possible de créer un conteneur léger. En modifiant le système d'exploitation, vous pouvez créer un environnement encore plus léger et que vous aimez.

Recommended Posts

Création d'un environnement Java léger qui s'exécute sur Docker
Créer une image docker pour exécuter une application Java simple
Créer un environnement de développement Java sur Mac
Création d'un environnement de développement pour les applications Web Java avec Docker pour Mac Part1
Consolidez les applications JavaFX dans des fichiers jar qui fonctionnent à la fois sur Java 8/11
Préparer un environnement de scraping avec Docker et Java
Créer un environnement de développement pour Docker, Java, vs code
Créer un environnement d'exécution Java sur Sakura VPS
Créez un environnement de développement Java à l'aide de jenv sur votre Mac
[Note] Créez un environnement Java à partir de zéro avec docker
Une commande qui nettoie définitivement l'environnement docker local
Essayez de créer un environnement de développement Java à l'aide de Docker
Oracle Java 8 sur Docker Ubuntu
Création d'un hôte Docker sur AWS à l'aide de Docker Machine (mémorandum personnel)
Essayez Hello World en utilisant Java brut sur le conteneur Docker
Créez un environnement Vue3 avec Docker!
Créer un environnement Node.js avec Docker
Créer un environnement XAMPP sur Ubuntu
Rails sur la procédure de construction de l'environnement Docker
Exécuter PureScript sur un conteneur Docker
Création d'un environnement haskell avec Docker + VS Code sur Windows10 Home
Créer un environnement de développement Unity sur docker
Installer l'environnement de développement Java sur Mac
Créez un environnement de développement d'applications Web qui utilise Java, MySQL et Redis avec Docker CE pour Windows
Accéder à MySQL sur un conteneur Docker à partir d'un programme Java local (OS hôte)
Comment créer un environnement de développement Ruby on Rails avec Docker (Rails 6.x)
Comment créer un environnement de développement Ruby on Rails avec Docker (Rails 5.x)
Créer un environnement de développement d'applications Web Java avec Docker pour Mac Part2
Créer un environnement de développement PureScript avec Docker
Mémo de construction de l'environnement de développement Java sur Mac
Utiliser docker dans un environnement proxy sur ubuntu 20.04.1
[Création] Un mémorandum sur le codage en Java
[Java] Comment résoudre un bogue dans le compilateur JDK
Créer un environnement d'exécution WAS à partir de Docker
Créons un environnement de développement Java (mise à jour)
[Ruby] Création d'un environnement de développement Ruby sur Ubuntu
Créer un environnement de développement Java 8 avec AWS Cloud 9
Construction de l'environnement de développement Java Spring Boot + Docker
Déployer des applications Web Java sur Heroku
Créer un environnement de lecture de code Redmine sur Docker
Création d'une classe de matrice dans Java Partie 1
Créer un environnement avec Docker sur AWS
Créez un environnement JMeter sur votre Mac
Installez Docker et créez un environnement d'exécution Java
Construction d'un environnement de développement simple Docker + Django
Un mémo qui a installé Ubuntu 20.4 sur HP Z2 Mini G4 et créé un environnement d'apprentissage profond avec Python Docker
[Première construction d'environnement] J'ai essayé de créer un environnement Rails6 + MySQL8.0 + Docker sur Windows 10.
J'ai créé un environnement Java EE sur AWS et essayé d'exécuter une application Web
Créez un environnement de développement pour créer des applications Ruby on Jets + React avec Docker
[Partie 1] Création d'un conteneur Docker qui fournit Markdown en HTML avec Apache / Pandoc
Créer un environnement de développement pour Docker + Rails6 + Postgresql
Essayez de créer un environnement Java 8 sur Amazon Linux2
[Memo] Créez facilement un environnement CentOS 8 avec Docker