Java 11应用程序作为轻量级Docker映像 [英] Java 11 application as lightweight docker image

查看:132
本文介绍了Java 11应用程序作为轻量级Docker映像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

受问题的启发,为什么Java 11基础Docker映像如此之大? (openjdk:11-jre-slim)我发现Java世界中的这个主题仍未解决。

Inspired by question Why is the Java 11 base Docker image so large? (openjdk:11-jre-slim) I found that this topic in Java world is still not settled.

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

As for 07 Dec 2018 there are common issues/pitfalls (discussed in the ticket above):


  • JRE是不作为单独的程序包分发。应该改用JDK的模块

  • JRE is not distributed as a separate "package". Modules from JDK should be used instead

Oracle OpenJDK 11 不支持 Linux Alpine ,因此 lightweight 无法轻松创建图像

Oracle OpenJDK 11 doesn't support Linux Alpine, so lightweight images can't be easily created

  • In the same time current stable Debian versions still doesn't have Java 11 packages (Ubuntu has Java 10 installed under openjdk-11 packages), that's why unstable sid versions are used for base docker images

当前可用的Oracle openjdk-11映像构建未剥离的 libjvm.so 模块,该模块具有数百兆字节,必须单独剥离:

currently available Oracle openjdk-11 images build unstripped libjvm.so module, which has hundreds megabyte and must be stripped separately:

  • jlink runtime image size (specifically libjvm.so) created from openjdk is huge. Expected it to be much smaller.
  • Solution: https://github.com/docker-library/openjdk/issues/217#issuecomment-436079779

由于这些问题,甚至 slim Oracle Java 11基本映像也很重并且被认为是不稳定的: https://hub.docker.com/_/openjdk/

As a result of these issues even slim Oracle Java 11 base images are quite heavy and considered to be unstable: https://hub.docker.com/_/openjdk/

所以问题是:

什么是优化的推荐的构建方式并将Java 11应用程序作为docker映像交付 ??

what are optimized or recommended ways to build and deliver Java 11 applications as docker images?

推荐答案

UPD从07.2019起:< a href = https://stackoverflow.com/a/57145029/907576> https://stackoverflow.com/a/57145029/907576

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

Taking as an example of simple spring boot application (with only one REST endpoint) so far i was able to figure out the following solutions (considering application jar is located at build/libs/spring-boot-demo.jar before Docker build:


  1. Jedi path 如果我们要在稳定的超薄Linux版本上使用 Oracle OpenJDK官方发行版 Debian 9 Stretch 现在):

  1. Jedi path if we want to use official Oracle OpenJDK distribution on stable slim Linux version (Debian 9 "Stretch" for now):

  • use debian:stretch-slim (latest stable) base image
  • use Docker multi-stage build


  1. 第一个Docker构建阶段:

  1. First Docker build stage:


  • 在第一个Docker构建阶段下载并安装 Oracle OpenJDK 存档

  • 使用 jlink 工具

  • download and install Oracle OpenJDK archive on the first Docker build stage
  • compile Java minimal distribution for your project (aka JRE) using jlink tool

第二个Docker构建阶段:

Second Docker build stage:


  • 从该阶段复制编译的最小Java发行版1到新映像

  • 配置访问Java的路径

  • 将应用程序jar复制到映像


因此,最终 Dockerfile 看起来像这样

So, final Dockerfile looks smth like this

实现JDK 版本 URL HASH ):

(actualize JDK VERSION, URL and HASH value):

# 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" ]

注意


  • 其中包括5个Java模块到最小的JRE示例( java.base,java.sql,java.naming,java.desktop,java.management,java.security.jgss,java.instrument )。我发现他们手动运行应用程序并修复 ClassNotFoundException 。等待更多的Spring Boot开发人员建议/指南,包括哪些Java模块以及何时包括,这与删除一些冗余依赖项相同,例如 java.desktop ,似乎仅用于对于 PropertyEditorSupport

  • ,如果您害怕错过某些模块-它们非常轻巧,它们总共提供了2个MB大小增加。获取 java。* jdk。* 11个模块的完整列表:

  • there are 5 java modules included to the minimal JRE example (java.base,java.sql,java.naming,java.desktop,java.management,java.security.jgss,java.instrument). I found them "manually" running the application and fixing ClassNotFoundException. Waiting for some further Spring Boot developers recommendations/guides which Java modules to include and when, as same as removing some redundant dependencies, like java.desktop, which seems to be used only for PropertyEditorSupport
  • if you are afraid to miss some modules - they are quite lightweight and all of them together give about 2 MB size increasing. Get a full list of java.* and jdk.* 11 modules:

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。* 模块

The resulting image size in my case was 123 MB with minimal 7 Spring Boot modules and 125 MB with all java.* modules

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


  • 预构建下载并提取了JDK的图像,并将其用作第一阶段的基础图像

  • 如果您每次都知道要包含哪些模块,请使用已编译的最小JRE和包含的模块预先构建基础图像

使用供应商的Open JDK发行版的简便方法

与Oracle相反> Azul的Zulu JDK 11 支持高山港口,并具有各自的基本 Docker映像

Opposite to Oracle Azul's Zulu JDK 11 supports Alpine port and has respective base Docker image.

因此,如果尊重Zulu JVM / JDK,则Docker构建会更加简单:

Thus, if Zulu JVM/JDK is respected, Docker build is much simpler:

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发行版预期的一样。

The resulting image is 73 MB, as expected with stripped Alpine distributions.

这篇关于Java 11应用程序作为轻量级Docker映像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆