建立基於Java 11的SpringBoot Docker映象到48M!

banq發表於2018-12-25

本文介紹使用AdoptOpenJDK的Alpine JDK 11版本,能夠將一個SpringBoot應用大小最小化到48M,DockerHub映象地址:https://hub.docker.com/r/shoutstar/spring-boot-jre-min-11

Dockerfile配置如下:

###########################################################
# spring-boot-jre-min-11
# Custom JRE from AdobtOpenJDK11 for spring-boot
# 
###########################################################
FROM adoptopenjdk/openjdk11:alpine AS builder

# create custom jre
RUN jlink \
    --module-path="${JAVA_HOME}/jmods" \
    --compress=2 \
    --add-modules=java.base,java.logging,java.xml,jdk.unsupported,java.sql,java.naming,java.desktop,java.management,java.security.jgss,java.instrument,jdk.charsets \
    --no-header-files \
    --no-man-pages \
    --verbose \
    --output=/opt/jre-min

# pull plane alpine
FROM alpine:3.8

ENV JAVA_HOME="/opt/jre-min"
ENV PATH="$PATH:/opt/jre-min/bin"
ENV JAVA_VERSION="jdk-11.0.1+13"
ENV JAVA_TOOL_OPTIONS="-XX:+UseContainerSupport"

# add glibc-compat
RUN apk --update add --no-cache ca-certificates curl openssl binutils xz \
    && GLIBC_VER="2.28-r0" \
    && ALPINE_GLIBC_REPO="https://github.com/sgerrand/alpine-pkg-glibc/releases/download" \
    && GCC_LIBS_URL="https://archive.archlinux.org/packages/g/gcc-libs/gcc-libs-8.2.1%2B20180831-1-x86_64.pkg.tar.xz" \
    && GCC_LIBS_SHA256=e4b39fb1f5957c5aab5c2ce0c46e03d30426f3b94b9992b009d417ff2d56af4d \
    && ZLIB_URL="https://archive.archlinux.org/packages/z/zlib/zlib-1%3A1.2.9-1-x86_64.pkg.tar.xz" \
    && ZLIB_SHA256=bb0959c08c1735de27abf01440a6f8a17c5c51e61c3b4c707e988c906d3b7f67 \
    && curl -Ls https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub -o /etc/apk/keys/sgerrand.rsa.pub \
    && curl -Ls ${ALPINE_GLIBC_REPO}/${GLIBC_VER}/glibc-${GLIBC_VER}.apk > /tmp/${GLIBC_VER}.apk \
    && apk add /tmp/${GLIBC_VER}.apk \
    && curl -Ls ${GCC_LIBS_URL} -o /tmp/gcc-libs.tar.xz \
    && echo "${GCC_LIBS_SHA256}  /tmp/gcc-libs.tar.xz" | sha256sum -c - \
    && mkdir /tmp/gcc \
    && tar -xf /tmp/gcc-libs.tar.xz -C /tmp/gcc \
    && mv /tmp/gcc/usr/lib/libgcc* /tmp/gcc/usr/lib/libstdc++* /usr/glibc-compat/lib \
    && strip /usr/glibc-compat/lib/libgcc_s.so.* /usr/glibc-compat/lib/libstdc++.so* \
    && curl -Ls ${ZLIB_URL} -o /tmp/libz.tar.xz \
    && echo "${ZLIB_SHA256}  /tmp/libz.tar.xz" | sha256sum -c - \
    && mkdir /tmp/libz \
    && tar -xf /tmp/libz.tar.xz -C /tmp/libz \
    && mv /tmp/libz/usr/lib/libz.so* /usr/glibc-compat/lib \
    && apk del binutils \
    && rm -rf /tmp/${GLIBC_VER}.apk /tmp/gcc /tmp/gcc-libs.tar.xz /tmp/libz /tmp/libz.tar.xz /var/cache/apk/*

COPY --from=builder /opt/jre-min /opt/jre-min


使用專門為Java應用構建映象工具:Jib
Jib是Google今年7月釋出OSS工具,幫助Java應用程式在使用Maven / Gradle時輸出為Docker映象,甚至在登錄檔中註冊。
Jib提供了一種機制,不僅可以自動推送DockerHub,還可以自動推送GCR的GCR和AWS的ECR。這是一個巨大的好處,你可以自動化它而無需編寫docker命令,也無需編寫Dockerfile 。
在Jib中,您可以在配置中指定from映象,但無法透過在此映象上執行上面的jlink來自定義它。因此,如果您希望jlink與自定義JRE一起執行,則需要先建立基本映象並將其釋出到登錄檔中。

在Jib中,除了PUSH到登錄檔之外,還支援向本地Docker守護程式註冊,建立tar等。

# 推到登錄檔
$ mvn compile jib:build

# 註冊到當地Docker守護程式
$ mvn compile jib:dockerBuild

# 建立tar
$ mvn compile jib:buildTar


設定使用Jav的Maven外掛:

<plugin>
    <groupId>com.google.cloud.tools</groupId>
    <artifactId>jib-maven-plugin</artifactId>
    <version>0.10.0</version>
    <configuration>
        <!-- 方便使用 -->
        <allowInsecureRegistries>true</allowInsecureRegistries>
        <from>
            <!-- 拉輕量級映象,這是僅在從DockerHub定製JRE -->
            <image>shoutstar/spring-boot-jre-min-11</image>
        </from>
        <to>
            <!-- 在構建期間透過-Djib.to.image取代 -->
            <image>future/sprinb-boot-app</image>
            <!-- 構建時- Djib.to.替換為credHelpr
            <credHelper>ecr-login</credHelper>
            -->
        </to>
        <container>
           
            <jvmFlags>
                <jvmFlag>-Dadd-opens=java.base/java.lang=ALL-UNNAMED</jvmFlag>
                <jvmFlag>-Dadd-opens=java.base/java.lang.invoke=ALL-UNNAMED</jvmFlag>
                <jvmFlag>-Dspring.profiles.active=${spring.profiles.active}</jvmFlag>
            </jvmFlags>
            <!-- 構建時建立映象的時間 -->
            <useCurrentTimestamp>true</useCurrentTimestamp>
        </container>
    </configuration>
</plugin>



 

相關文章