受问题启发,为什么Java 11基本Docker映像这么大?(openjdk:11-jre-slim)我发现Java世界中的这个话题仍然没有解决。
至于07 Dec 2018常见问题/陷阱(在上面的票证中讨论):
07 Dec 2018
JRE没有作为单独的“包”分发。应改用JDK的模块
Oracle OpenJDK 11不支持Linux Alpine,因此无法轻松创建 轻量级 映像
当前可用的Oracle openjdk-11映像构建未剥离的libjvm.so模块,该模块具有数百兆字节,必须分别剥离:
libjvm.so
从openjdk创建的jlink运行时映像大小(特别是libjvm.so)很大。期望它会小得多。
由于这些问题,即使是 苗条的 Oracle Java 11基本映像也很沉重,并被认为是不稳定的:https : //hub.docker.com/_/openjdk/
所以问题是:
有什么 优化的 或 推荐的 方法来构建和交付Java 11应用程序作为docker映像?
到目前为止,以简单的spring boot应用程序为例(只有一个REST端点),我能够找出以下解决方案(考虑到应用程序jar位于build/libs/spring-boot- demo.jarDocker构建之前):
build/libs/spring-boot- demo.jar
__如果我们想 在稳定的超薄Linux版本上 使用 Oracle OpenJDK官方发行版的 绝地路径 (Debian 9 "Stretch"目前):
Debian 9 "Stretch"
debian:stretch-slim
使用Docker多阶段构建
第一个Docker构建阶段:
Oracle OpenJDK
使用jlink工具为您的项目(又名JRE)编译Java最小发行版
jlink
从第1阶段将已编译的最小Java发行版复制到新映像
所以,最终Dockerfile看起来像这样
Dockerfile
( 具体化JDKVERSION,URL和HASH值):
VERSION
URL
HASH
# First stage: JDK 11 with modules required for Spring Boot FROM debian:stretch-slim as packager # source JDK distribution names # update from https://jdk.java.net/java-se-ri/11 ENV JDK_VERSION="11.0.1" ENV JDK_URL="https://download.java.net/java/GA/jdk11/13/GPL/openjdk-${JDK_VERSION}_linux-x64_bin.tar.gz" ENV JDK_HASH="7a6bb980b9c91c478421f865087ad2d69086a0583aeeb9e69204785e8e97dcfd" ENV JDK_HASH_FILE="${JDK_ARJ_FILE}.sha2" ENV JDK_ARJ_FILE="openjdk-${JDK_VERSION}.tar.gz" # target JDK installation names ENV OPT="/opt" ENV JKD_DIR_NAME="jdk-${JDK_VERSION}" ENV JAVA_HOME="${OPT}/${JKD_DIR_NAME}" ENV JAVA_MINIMAL="${OPT}/java-minimal" # downlodad JDK to the local file ADD "$JDK_URL" "$JDK_ARJ_FILE" # verify downloaded file hashsum RUN { \ echo "Verify downloaded JDK file $JDK_ARJ_FILE:" && \ echo "$JDK_HASH $JDK_ARJ_FILE" > "$JDK_HASH_FILE" && \ sha256sum -c "$JDK_HASH_FILE" ; \ } # extract JDK and add to PATH RUN { \ echo "Unpack downloaded JDK to ${JAVA_HOME}/:" && \ mkdir -p "$OPT" && \ tar xf "$JDK_ARJ_FILE" -C "$OPT" ; \ } ENV PATH="$PATH:$JAVA_HOME/bin" RUN { \ java --version ; \ echo "jlink version:" && \ jlink --version ; \ } # build modules distribution RUN jlink \ --verbose \ --add-modules \ java.base,java.sql,java.naming,java.desktop,java.management,java.security.jgss,java.instrument \ # java.naming - javax/naming/NamingException # java.desktop - java/beans/PropertyEditorSupport # java.management - javax/management/MBeanServer # java.security.jgss - org/ietf/jgss/GSSException # java.instrument - java/lang/instrument/IllegalClassFormatException --compress 2 \ --strip-debug \ --no-header-files \ --no-man-pages \ --output "$JAVA_MINIMAL" # Second stage, add only our minimal "JRE" distr and our app FROM debian:stretch-slim ENV JAVA_HOME=/opt/java-minimal ENV PATH="$PATH:$JAVA_HOME/bin" COPY --from=packager "$JAVA_HOME" "$JAVA_HOME" COPY "build/libs/spring-boot-demo.jar" "/app.jar" EXPOSE 8080 CMD [ "-jar", "/app.jar" ] ENTRYPOINT [ "java" ]
注意事项 :
* 最小JRE示例(`java.base,java.sql,java.naming,java.desktop,java.management,java.security.jgss,java.instrument`)中包含5个Java模块。我发现他们“手动”运行应用程序并修复`ClassNotFoundException`。等待更多的Spring Boot开发人员建议/指南,包括哪些Java模块以及何时包括,这与删除一些冗余依赖项(如)相同`java.desktop`,似乎仅用于`PropertyEditorSupport` * 如果您害怕错过某些模块-它们非常轻巧,并且所有模块加在一起大约增加2 MB的大小。获取`java.*`和`jdk.*`11个模块的完整列表:
java --list-modules | grep -E "^java\.[^@]*" | cut -d @ -f 1 java --list-modules | grep -E "^jdk\.[^@]*" | cut -d @ -f 1
java --list-modules | grep -E "^java\.[^@]*" | cut -d @ -f 1
java --list-modules | grep -E "^jdk\.[^@]*" | cut -d @ -f 1
在我的情况下,最终的映像大小为 123 MB (最少7个Spring Boot模块),所有模块为 125 MBjava.*
java.*
作为此构建工作流程的可选改进 :
* 使用下载并提取的JDK预先构建映像,并将其用作第一阶段的基础映像 * 如果您每次都知道要包含哪些模块,请使用已编译的最小JRE和包含的模块预先构建基本映像
与Oracle Azul相反,Zulu JDK 11支持Alpine端口并具有各自的基础Docker映像。
因此,如果尊重Zulu JVM / JDK,则Docker构建会简单得多:
FROM azul/zulu-openjdk-alpine:11 as packager RUN { \ java --version ; \ echo "jlink version:" && \ jlink --version ; \ } ENV JAVA_MINIMAL=/opt/jre # build modules distribution RUN jlink \ --verbose \ --add-modules \ java.base,java.sql,java.naming,java.desktop,java.management,java.security.jgss,java.instrument \ # java.naming - javax/naming/NamingException # java.desktop - java/beans/PropertyEditorSupport # java.management - javax/management/MBeanServer # java.security.jgss - org/ietf/jgss/GSSException # java.instrument - java/lang/instrument/IllegalClassFormatException --compress 2 \ --strip-debug \ --no-header-files \ --no-man-pages \ --output "$JAVA_MINIMAL" # Second stage, add only our minimal "JRE" distr and our app FROM alpine ENV JAVA_MINIMAL=/opt/jre ENV PATH="$PATH:$JAVA_MINIMAL/bin" COPY --from=packager "$JAVA_MINIMAL" "$JAVA_MINIMAL" COPY "build/libs/spring-boot-demo.jar" "/app.jar" EXPOSE 8080 CMD [ "-jar", "/app.jar" ] ENTRYPOINT [ "java" ]
生成的图像为 73 MB ,与剥离的Alpine发行版预期的一样。