Basierend auf Java in einer Welt der Container auf Japanisch bei der Oracle Groundbreakers APAC Tour in Tokio am 13.11 Ich schreibe in.
Die folgende Abbildung zeigt ein Moduldiagramm von Java9 oder höher.
Beim Schreiben einer Anwendung in Java wird selten alles in diesem Moduldiagramm verwendet. Zum Beispiel sind java.xml, corba, javaws oft nicht notwendig.
Wenn Sie ein Docker-Image mit Linux und JDK erstellen, ohne mit Docker darüber nachzudenken, ist es ziemlich groß. Daher wird oft behauptet, dass Container und Java nicht kompatibel sind. Große Kapazität, schwerer, langsamer Start usw. Die Funktionen von Java sind jedoch auch ideal für Container. Es gibt viele Vorteile wie Laufzeit-, Hardware- und Betriebssystemunabhängigkeit, JVM-garantierte Sicherheitskompatibilität, garantierte stabile Ausführung bei Änderungen der Umgebung, Ökosystem und die beste Auswahl an Containern. .. Ein JDK, das standardmäßig zu schwer ist, kann verbessert werden, indem das JDK selbst mit Jigsaw modularisiert und die Abhängigkeiten organisiert werden.
Dockerfile
Das Betriebssystem erstellt ein Image mit ubuntu: latest. Erstellen Sie zunächst eine Umgebung mit der Standardgröße und versuchen Sie es mit 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" ]
Erstellen Sie das Image und führen Sie es aus.
$ 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!
Schauen wir uns das erstellte Bild an.
$ docker images helloworld-java
REPOSITORY TAG IMAGE ID CREATED SIZE
helloworld-java latest 682ae9922b5b 2 minutes ago 396MB
Es gibt ungefähr 400 MB.
Erstellen Sie eine benutzerdefinierte JRE mit jdeps und jlink. Sie können die Modulabhängigkeiten mithilfe von jdeps anzeigen. Werfen wir einen Blick auf das Hello World-Modul.
$ jdeps --list-deps HelloWorld.class
java.base
Da der Inhalt Hello World ist, gibt es nur wenige Abhängigkeiten. Auf der HelloWorld-Ebene wird anscheinend nur das Modul java.base verwendet.
Erstellen wir eine benutzerdefinierte JRE mit jlink.
jlink --compress=2 --module-path $JAVA_HOME/jmods --add-modules java.base --output jre-min
Es wird nur java.base verwendet, daher wird nur Add-Module angegeben. Nach der Ausführung wird jre-min erstellt. In dieser Umgebung ist Hello World das Minimum, das zum Ausführen erforderlich ist. Die Kapazität betrug ebenfalls 27 MB.
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
Lassen Sie uns Hello World in dieser minimalen Umgebung ausführen.
$ 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!
Lassen Sie uns eine benutzerdefinierte JRE mit jlink erstellen und erstellen.
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!
Die Größe beträgt weniger als ein Viertel der vorherigen.
Wir haben das minimal erforderliche Java, aber wir haben immer noch 123 MB. Wenn nur die Methode früher verwendet wird, kann nur Java leichter gemacht werden, daher werden wir auch das Betriebssystem ändern. Wenn Sie nur ava ausführen möchten, ist Ubuntu zu luxuriös. Verwenden Sie daher alpines Linux, um die minimal erforderliche Linux-Umgebung zu erstellen. alpine ist ein leichtes Linux, das auf musl libc und BusyBox basiert (es enthält wirklich nichts ...). Die Mindestkonfiguration scheint leichter als 5 MB zu sein. Siehe von AdoptOpenJDK veröffentlichte Docker-Datei für alpine Java-Umgebungen Erstellen Sie ein Image mit der Mindestkonfiguration.
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
Es ist weniger als die Hälfte des vorherigen. Es ist ungefähr 1/8 des ursprünglichen.
Natürlich kann es ausgeführt werden
$ 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!
Es scheint, dass oft gesagt wird, dass der Container und Java aufgrund ihrer großen Kapazität, ihres hohen Gewichts und ihres langsamen Starts nicht miteinander kompatibel sind. Nach JDK9 können Sie mit jdeps und jlink eine dedizierte Umgebung erstellen. Da es möglich ist, die minimal erforderliche Umgebung zu erstellen, ist es möglich, einen Lichtbehälter zu erstellen. Durch Ändern des Betriebssystems können Sie eine Umgebung erstellen, die noch leichter ist und Ihnen gefällt.
Recommended Posts