一、思考

由于 Oracle JDK 17 开始,Oracle 不再提供单独的 JRE 下载。但是,我们可以使用 jlink 工具来自定义运行时镜像,从而减小镜像大小。

步骤:

  1. 在构建阶段,使用完整的 JDK 来编译和运行应用程序(如果需要编译)。

  2. 使用 jlink 工具创建一个定制的 JRE 运行时,只包含应用程序所需的模块。

  3. 在最终镜像中只包含定制的 JRE。

但是,如果你只是需要运行一个 Java 应用程序,并且不需要编译,那么可以使用 jlink 从 JDK 中生成一个定制的 JRE。

由于 Dockerfile 中直接使用了 jdk17.tar.gz,我假设你已经有 Oracle JDK 17 的压缩包。我们可以这样做:

修改 Dockerfile,在安装 JDK 后,使用 jlink 生成一个定制的 JRE,然后删除完整的 JDK。

但是注意:Oracle JDK 17 的许可协议可能不允许随意分发,请确保你遵守相关许可。

另外,也可以考虑使用 OpenJDK,它通常更友好。

如果你坚持使用 Oracle JDK 17,并且已经下载了 tar.gz,那么可以按照以下步骤:

  1. 在 Dockerfile 中,解压 JDK。

  2. 使用 jlink 生成一个定制的 JRE(需要知道你的应用程序依赖哪些模块)。

  3. 删除原始的 JDK,只保留生成的 JRE。

示例 Dockerfile 修改部分:

假设你的应用程序只需要 java.base 模块(实际上可能不够,你需要根据你的应用程序需求来确定模块列表)。

但是,如果不知道具体模块,可以先使用完整 JDK 运行,然后通过命令 jdeps 来分析依赖。

由于在 Docker 构建中,我们可能没有应用程序的 jar 文件,或者构建过程复杂,这里提供一个思路:

如果你知道应用程序的模块依赖,可以这样:

在 Dockerfile 中:
ADD jdk17.tar.gz /work/
RUN /work/jdk-17.0.x/bin/jlink --no-header-files --no-man-pages --compress=2 --strip-debug --add-modules java.base,java.sql,java.desktop,java.naming,java.management,java.security.jgss,java.instrument --output /work/jre17

然后设置环境变量指向这个定制的 JRE。

但是,请注意,这个模块列表只是示例,你的应用程序可能需要更多模块。

如果你无法确定模块列表,可以考虑使用完整的 JDK 运行时,但这样大小减少有限。

另一种方案:使用 OpenJDK 的官方镜像,它们通常提供了 slim 版本,或者你可以使用 jlink 自己构建。

由于你使用的是 Anolis OS,并且可能希望使用 Oracle JDK,这里给出一个使用 jlink 裁剪的示例 Dockerfile 修改:

我们将原始 Dockerfile 修改为:

  1. 安装 JDK

  2. 使用 jlink 生成定制 JRE

  3. 删除 JDK,只保留 JRE

  4. 环境变量指向 JRE

修改后的 Dockerfile 示例:

FROM registry.openanolis.cn/openanolis/anolisos:8.9

RUN mkdir -p /work /usr/local/share/fonts/chinese && \
    yum install -y fontconfig ttmkfdir && \
    yum clean all && \
    rm -rf /var/cache/yum /tmp/* /var/tmp/*

# 添加 JDK
ADD jdk17.tar.gz /work/

# 假设解压后目录为 jdk-17.0.x
# 使用 jlink 生成定制 JRE,这里模块列表需要根据你的应用程序调整
RUN /work/jdk-17.0.x/bin/jlink \
    --module-path /work/jdk-17.0.x/jmods \
    --add-modules java.base,java.sql,java.desktop,java.naming,java.management,java.security.jgss,java.instrument \
    --strip-debug \
    --no-header-files \
    --no-man-pages \
    --compress=2 \
    --output /work/jre17

# 删除 JDK,只保留 JRE
RUN rm -rf /work/jdk-17.0.x

# 复制字体
COPY fonts/* /usr/local/share/fonts/chinese/
RUN fc-cache -fv

# 时区
COPY Shanghai /etc/localtime

# 设置环境变量,使用 JRE
ENV JAVA_HOME=/work/jre17 \
    PATH=$PATH:/work/jre17/bin \
    LANG=zh_CN.UTF-8

EXPOSE 8080

注意:上面的模块列表(--add-modules)是示例,你可能需要根据你的应用程序来调整。如果不确定,可以先使用完整 JDK 运行,然后通过 jdeps 工具分析依赖,再调整模块列表。

另外,如果你使用的是 Spring Boot 应用程序,并且是打包成可执行 jar,那么你可以使用以下命令来生成模块列表:

在主机上,使用 JDK 的 jdeps 命令:
jdeps --ignore-missing-deps -q --print-module-deps your-application.jar

这个命令会输出模块列表,用逗号分隔,可以直接用在 jlink 的 --add-modules 参数中。

但是,请注意,有些依赖可能无法被 jdeps 自动发现,特别是使用反射的情况。你可能需要手动添加一些模块。

如果没有办法分析,另一个折中方案是使用 java.se 模块集,它包含了 Java SE 标准版的所有模块,但比完整 JDK 小。

使用 --add-modules java.se 即可。

但是,请注意,从 JDK 17 开始,模块系统有所变化,确保你的模块名称正确。

最后,由于裁剪 JRE 需要了解应用程序的模块依赖,如果裁剪过度可能导致应用程序运行失败。建议先在测试环境中验证。

如果你希望更简单,也可以考虑使用 OpenJDK 的官方镜像,它们提供了 slim 版本,通常已经经过裁剪。

希望这些信息对你有帮助。

二、重要须知

自 JDK 11 开始,Oracle 不再单独提供 JRE 下载。这是因为:

  1. 模块化系统(Jigsaw 项目)允许用户自行构建定制化运行时

  2. 需要使用 jlink 工具从完整的 JDK 创建自定义 JRE

三、替代方案

3.1 方案1:使用 jlink 创建自定义 JRE

# 在构建过程中创建最小 JRE
FROM registry.openanolis.cn/openanolis/anolisos:8.9 AS jdk-builder

# 下载完整 JDK
ADD https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.tar.gz /tmp/jdk.tar.gz
RUN tar -xzf /tmp/jdk.tar.gz -C /opt && \
    rm /tmp/jdk.tar.gz

# 使用 jlink 创建自定义 JRE(示例:只包含必要模块)
RUN /opt/jdk-17*/bin/jlink \
    --module-path /opt/jdk-17*/jmods \
    --add-modules java.base,java.sql,java.desktop,java.naming,java.management,java.security.jgss,java.instrument \
    --strip-debug \
    --no-header-files \
    --no-man-pages \
    --compress=2 \
    --output /opt/jre-17-custom

# 然后复制 /opt/jre-17-custom 到最终镜像

3.2 方案2:使用 OpenJDK(推荐,免费)

# 使用 OpenJDK 官方镜像
FROM openjdk:17-jdk-slim

# 或使用 alpine 版本(更小)
FROM openjdk:17-jdk-alpine

3.3 方案3:使用 Adoptium(原AdoptOpenJDK)

# 使用 Eclipse Temurin(原AdoptOpenJDK)
FROM eclipse-temurin:17-jre

# 或 JDK 版本
FROM eclipse-temurin:17-jdk

四、JDK 下载地址

4.1 oracle jdk 17

https://www.oracle.com/java/technologies/downloads/#java17


需要注册 Oracle 账户

有商业使用许可限制

4.2 OpenJDK 17(开源免费)

https://jdk.java.net/17/

直接下载

无商业限制

4.3 Amazon Corretto 17(AWS维护)

https://docs.aws.amazon.com/corretto/latest/corretto-17-ug/downloads-list.html

生产就绪

长期支持

五、Docker 优化示例

5.1 使用 OpenJDK 官方镜像

FROM registry.openanolis.cn/openanolis/anolisos:8.9

# 安装 OpenJDK 17
RUN yum install -y java-17-openjdk java-17-openjdk-devel && \
    yum clean all && \
    rm -rf /var/cache/yum

# 设置环境变量
ENV JAVA_HOME=/usr/lib/jvm/java-17-openjdk \
    PATH=$PATH:/usr/lib/jvm/java-17-openjdk/bin \
    LANG=zh_CN.UTF-8

5.2 使用多阶段构建创建最小 JRE

# 第一阶段:构建 JRE
FROM openjdk:17-jdk-slim as builder

# 创建自定义 JRE(只包含必要模块)
RUN jlink \
    --add-modules java.base,java.sql,java.desktop,java.naming \
    --strip-debug \
    --no-man-pages \
    --no-header-files \
    --compress=2 \
    --output /custom-jre

# 第二阶段:最终镜像
FROM registry.openanolis.cn/openanolis/anolisos:8.9-slim

# 复制自定义 JRE
COPY --from=builder /custom-jre /opt/java

# 设置环境
ENV JAVA_HOME=/opt/java \
    PATH=$PATH:/opt/java/bin \
    LANG=zh_CN.UTF-8

# 其他配置...

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐