docker - 删除不再需要的文件后如何回收 Docker Image 中的空间(用于制作 jre 的 java jdk 11)

标签 docker java-11 jlink

我将 Docker 与 Java 应用程序一起使用,以前我使用 Java 8 JRE 并且我的总 docker 镜像大小为 163MB ,然后我转而使用 Java 11 JRE 并且大小增加到 2320MB _0x10456,我不想增加如果可能的话。

但是 Java 11 允许您构建自己的 JRE(使用 JDK 中的 jlink),其中仅包含您需要的模块。所以我修改了我的 DockerFile 以基于 JDK 而不是 JRE,然后我用它来构建 JRE,只包含我需要的模块,并在我的应用程序文件夹中创建它。然后我使用 rm -fr /opt/java 删除 JDK,因为我不再需要它,假设这会缩小图像大小,但现在图像不是 553MB 。我的应用程序运行,但如果我不能缩小图像大小,使用 jlink 毫无意义,我做错了什么?

Docker 文件如下:

FROM adoptopenjdk/openjdk11:alpine

RUN apk --no-cache add \
      ca-certificates \
      curl \
      fontconfig \
      msttcorefonts-installer \
      tini \
 && update-ms-fonts \
 && fc-cache -f

RUN mkdir -p /opt \
 && curl http://www.jthink.net/songkong/downloads/build1114/songkong-linux-docker.tgz?val=130| tar -C /opt -xzf - \
&& find /opt/songkong -perm /u+x -type f -print0 | xargs -0 chmod a+x

RUN /opt/java/openjdk/bin/jlink --module-path=/opt/java/openjdk/jmods \
--add-modules java.desktop,java.datatransfer,java.logging,java.management,java.naming,java.net.http,java.prefs,java.scripting,java.sql,jdk.management,jdk.unsupported,jdk.scripting.nashorn \
--output /opt/songkong/jre

RUN rm -fr /opt/java

EXPOSE 4567

ENTRYPOINT ["/sbin/tini"]

# Config, License, Logs, Reports and Internal Database
VOLUME /songkong

# Music folder should be mounted here
VOLUME /music

WORKDIR /opt/songkong

CMD /opt/songkong/songkongremote.sh

最佳答案

Docker 镜像的性质是正常的。
Docker 镜像基于堆叠在一起的多个层,并且每一层都是不可变的(无法更新另一层的内容)。

因此,当一个文件在一层中创建并在另一层中删除时,该文件仍然存在,但不再可用,并且 Dockerfile 中的大多数指令都会创建一个新层。

在您的情况下,我们会将您的图像减少到 3 层以进行演示:

[Layer that remove the /opt/java folder]
[Layer with the new JRE]
[Base image with the JDK]

但是,总的来说,您的图像具有包含所有数据的 3 层。
您可以通过运行 docker image history myimage 将其可视化,您将获得图层列表及其大小。

如果要减小大小,则需要进行多阶段构建:
- 第一阶段创建 JRE
- 第二阶段导入 JRE 并在其上添加您的代码

每个阶段都有不同的基础镜像,所以第二个阶段可以使用一个小的基础镜像:
# First stage - Create the JRE
FROM adoptopenjdk/openjdk11:alpine AS jre

RUN /opt/java/openjdk/bin/jlink --module-path=/opt/java/openjdk/jmods \
--add-modules java.desktop,java.datatransfer,java.logging,java.management,java.naming,java.net.http,java.prefs,java.scripting,java.sql,jdk.management,jdk.unsupported,jdk.scripting.nashorn \
--output /opt/songkong/jre

# Second stage
FROM alpine
RUN apk --no-cache add \
      ca-certificates \
      curl \
      fontconfig \
      msttcorefonts-installer \
      tini \
 && update-ms-fonts \
 && fc-cache -f

COPY --from=jre /opt/songkong/jre /opt/songkong/jre

RUN mkdir -p /opt \
 && curl http://www.jthink.net/songkong/downloads/build1114/songkong-linux-docker.tgz?val=130| tar -C /opt -xzf - \
&& find /opt/songkong -perm /u+x -type f -print0 | xargs -0 chmod a+x

EXPOSE 4567

ENTRYPOINT ["/sbin/tini"]

# Config, License, Logs, Reports and Internal Database
VOLUME /songkong

# Music folder should be mounted here
VOLUME /music

WORKDIR /opt/songkong

CMD /opt/songkong/songkongremote.sh

有关多阶段构建的更多信息:https://docs.docker.com/develop/develop-images/multistage-build/

有关图像和图层的更多信息:https://docs.docker.com/storage/storagedriver/#images-and-layers

关于docker - 删除不再需要的文件后如何回收 Docker Image 中的空间(用于制作 jre 的 java jdk 11),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61390821/

相关文章:

java - 编译依赖于外部 Jar 的模块

python - 无法访问使用 docker 和 google cloud 部署的应用程序

bash - Docker 检查数据库是否正在运行

docker - Redis桌面管理器无法在docker中连接redis?

java - 使用 Java 11 HttpClient 读取分块数据

java - 如何在没有CMD窗口的情况下运行jlink生成的Java运行时镜像?

docker - 如何在 Docker 上启动 Solr techproducts 示例?

使用 .NET 6 或更高版本时需要 Java SDK 11.0 或更高版本

docker - 在docker中安装Java时无法找到包

kotlin - jlink:在合并模块和 kotlin.stdlib 中打包 kotlin.*