为什么Java 11基础Docker镜像(openjdk:11-jre-slim)这么大?

201

Java 11 被宣布为最新的 LTS 版本。因此,我们正在尝试基于这个 Java 版本启动新服务。

然而,Java 11 的基础 Docker 镜像比 Java 8 的相应镜像要大得多:

(我只考虑每个 Java 版本中官方 OpenJDK最轻量级的镜像。)

进一步挖掘发现以下“问题”:

  • openjdk:11-jre-slim 镜像使用了基础镜像 debian:sid-slim。这带来了两个问题:

    • 这比 alpine:3.8 大 60 MB。

    • Debian sid 版本是不稳定的。

  • 镜像中安装的 openjdk-11-jre-headless 包(在运行 Docker 容器内)比 openjdk8-jre3倍

    • openjdk:8-jre-alpine

      / # du -hs /usr/lib/jvm/java-1.8-openjdk/jre/lib/
      57.5M   /usr/lib/jvm/java-1.8-openjdk/jre/lib/
      
      openjdk:11-jre-slim
      # du -sh /usr/lib/jvm/java-11-openjdk-amd64/lib/
      179M    /usr/lib/jvm/java-11-openjdk-amd64/lib/
      
      深入研究后,我发现这种沉重感的“根源”——就在JDK的modules文件中。
      # ls -lhG /usr/lib/jvm/java-11-openjdk-amd64/lib/modules
      135M    /usr/lib/jvm/java-11-openjdk-amd64/lib/modules
      

因此,现在出现了以下问题:

  • 为什么alpine不再作为Java 11精简映像的基础镜像?

  • 为什么LTS Java映像使用不稳定的sid版本?

  • 为什么OpenJDK 11的精简/无头/JRE包与类似的OpenJDK 8包相比如此之大?

    • modules文件是什么,在OpenJDK 11中占据了135 MB?

更新: 对于这些挑战的解决方案,可以使用这个答案: Java 11 application as docker image


1
首先,Java的新版本(JDK 9+)已经进行了模块化处理,这就解释了为什么11和8之间存在模块的差异。 - Zachary Craig
14
没有JRE 11,所以你拥有的是完整的JDK。你可以创建紧凑的环境,甚至比JRE 8更轻巧,但需要一个实际的模块化应用程序,这样依赖关系就会被知晓。 - Holger
1
除此之外,你发现导致应用程序大小增加的那些模块并不是所有都是必需的。但是为了找出哪些是必需的,你应该采取创建模块化应用程序的步骤。你可以了解更多关于[tag:jlink](在Java9中引入)的内容。 - Naman
1
现在阅读这篇文章的在线版本再合适不过了 - https://twitter.com/LogicTheoryIO/status/1064503559071371265 - Naman
显示剩余4条评论
4个回答

206
为什么alpine不再用作Java 11 slim镜像的基础映像?这是因为目前没有官方稳定的适用于Alpine的OpenJDK 11构建。Alpine使用musl libc,而大多数Linux使用的是标准glibc,这意味着JVM必须与musl libc兼容才能支持vanilla Alpine。musl OpenJDK端口正在OpenJDK的Portola项目下开发。当前状态在OpenJDK 11页面上概述:此页面上先前提供的Alpine Linux构建已于JDK 11 GA时被删除。它不是生产就绪的,因为没有经过足够的测试来被视为GA构建。请使用早期访问JDK 12 Alpine Linux构建代替。目前,Alpine的唯一稳定OpenJDK版本是由IcedTea项目提供的7和8版本。但是-如果您愿意考虑官方OpenJDK以外的其他选项,则Azul's Zulu OpenJDK提供了一个引人注目的替代方案:
  • 它支持Java 11 on Alpine musl(截至撰写本文时为11.0.2版本);
  • 它是经过认证的OpenJDK构建,使用OpenJDK TCK合规性套件进行验证;
  • 它是免费、开源和Docker准备就绪(Dockerhub)。

有关支持可用性和路线图,请参见Azul support roadmap

更新,2019年3月6日:从昨天开始,openjdk11已在Alpine存储库中提供!可以在Alpine上使用以下方式获取:

apk --no-cache add openjdk11

该软件包基于jdk11u OpenJDK分支,加入了来自Portola项目的修复程序,并引入以下PR。向Alpine团队致敬和感谢。
“为什么LTS Java镜像使用不稳定的sid版本?”这是一个公平的问题/请求。实际上,已经有一个提供Java 11在稳定版Debian上运行的开放票据:
https://github.com/docker-library/openjdk/issues/237 更新,2018年12月26日:问题已得到解决,现在OpenJDK 11 slim映像基于最近可用的stretch-backports OpenJDK 11(PR link)。
“为什么OpenJDK 11的slim/headless/JRE软件包与类似的OpenJDK 8软件包相比如此大?这个modules文件是什么,在OpenJDK 11中带来了135MB?”

Java 9引入了模块化系统,相比于jar文件,这是一种新的和改进的打包packages和资源的方法。这篇来自Oracle的文章详细介绍了这个功能:
https://www.oracle.com/corporate/features/understanding-java-9-modules.html

modules文件捆绑了所有随JRE一起提供的模块。可以使用java --list-modules命令打印出完整的模块列表。modules是一个非常大的文件,它包含了所有标准模块,并且因此相当臃肿。

需要注意的一件事情是,它替代了已经过时的rt.jartools.jar等内容。因此,在与9之前的OpenJDK版本进行比较时,应该减去rt.jartools.jar的大小(它们组合起来应该占用约80MB)。


18
如果您只考虑官方镜像,并且目标是使用可用的较小JRE镜像,我建议您查看官方的OpenJDK镜像openjdk:11-jre-slim-buster,其大小仅为69.2 MB。

https://hub.docker.com/layers/openjdk/library/openjdk/11.0.9-jre-slim-buster/ - Alex Punnen
openjdk:11-jre-slim-buster 的镜像大小为 129.7MB !!! - Zhasulan Berdibekov
1
@ЖасуланБердибеков 我指的是压缩后的大小,这是比较运行时图像大小的良好指标。请参见:https://hub.docker.com/layers/openjdk/library/openjdk/11.0.11-jre-slim-buster/images/sha256-1efc10742a26c56416e400611b1d7ba871dab6c478e8017ab0a226d87f26b78b?context=explore - Davide Martorana

13

至于2019年7月份,https://adoptopenjdk.net/已经正式支持Java 11的Alpine版本:

但是,当你组装最小化应用程序时,仍需考虑模块(jmodsjlink)。

注意slim镜像不包含某些模块(如java.sql) - 它们被明确地排除了 (https://github.com/AdoptOpenJDK/openjdk-docker/blob/21b8393b9c23f94d6921a56cce27b026537c6ca2/11/jdk/alpine/slim-java.sh#L233)


感谢您的有用回答,我现在明白了瘦身镜像中排除了什么。但我有一个问题,为什么它也排除了java.se模块,这不是必需的吗? - lmk
Eclipse Temurin镜像也许会很有趣:https://hub.docker.com/_/eclipse-temurin - aemaem

2

1
出于好奇,你知道这两个镜像之间的区别吗?11.0.7-jre-slim-buster 和 11.0.7-jre-slim - hafiz ali
1
buster、jessie或stretch是Debian发行版的套件代码名称,表示镜像基于哪个版本。 - Javier Aviles

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接