gpt4 book ai didi

Java 11 应用程序作为轻量级 docker 镜像

转载 作者:IT老高 更新时间:2023-10-28 12:35:50 32 4
gpt4 key购买 nike

受问题启发 Why is the Java 11 base Docker image so large? (openjdk:11-jre-slim)我发现Java世界的这个话题还没有定论。

至于 2018 年 12 月 7 日 有一些常见问题/陷阱(在上面的票中讨论):

由于这些问题,即使是 slim Oracle Java 11 基础镜像也非常繁重,被认为是不稳定的:https://hub.docker.com/_/openjdk/

所以问题是:

有哪些优化推荐方法来构建和交付 Java 11 应用程序作为 Docker 镜像

最佳答案

从 07.2019 开始更新:https://stackoverflow.com/a/57145029/907576

以简单的 Spring Boot 应用程序(只有一个 REST 端点)为例,到目前为止,我能够找出以下解决方案(考虑到应用程序 jar 在 Docker 构建之前位于 build/libs/spring-boot-demo.jar:

  1. Jedi 路径如果我们想在稳定的超薄 Linux 版本上使用 官方 Oracle OpenJDK 发行版(目前为 Debian 9 "Stretch"):

    • 使用 debian:stretch-slim (最新稳定版)基础镜像
    • 使用 Docker multi-stage build

      1. 第一个 Docker 构建阶段:

        • 下载安装Oracle OpenJDK在第一个 Docker 构建阶段存档
        • 使用 jlink 为您的项目(又名 JRE)编译 Java 最小发行版工具
      2. 第二个 Docker 构建阶段:

        • 将已编译的最小 Java 分发从阶段 1 复制到新镜像
        • 配置访问Java的路径
        • 将应用程序 jar 复制到镜像中

    所以,最终 Dockerfile看起来像这样

    (实现 JDK VERSIONURLHASH):

    # 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

    在我的情况下,生成的图像大小为 123 MB,最少 7 个 Spring Boot 模块,125 MB,所有 java.*模块

    作为此构建工作流程的可选改进:

    • 使用下载并解压的 JDK 预构建镜像,并将其用作第一阶段的基础镜像
    • 如果您知道每次要包含哪些模块 - 使用已编译的最小 JRE 和包含的模块预先构建一个基础镜像
  2. 轻松使用供应商的 Open JDK 发行版:

    相对于甲骨文Azul's Zulu JDK 11支持Alpine port并有各自的基地Docker image .

因此,如果尊重 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 分布一致。

关于Java 11 应用程序作为轻量级 docker 镜像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53669151/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com