Hola usuario de nuestra web, encontramos la respuesta a tu interrogante, desplázate y la verás un poco más abajo.
Solución:
UPD de 07.2019: https://stackoverflow.com/a/57145029/907576
Tomando como ejemplo la aplicación de arranque de primavera simple (con solo un punto final REST) hasta ahora, pude descubrir las siguientes soluciones (considerando que el contenedor de la aplicación se encuentra en build/libs/spring-boot-demo.jar
antes de la compilación de Docker:
-
Camino Jedi si queremos usar distribución oficial de Oracle OpenJDK en una versión delgada estable de Linux (
Debian 9 "Stretch"
por ahora):- usar
debian:stretch-slim
(última imagen estable) base -
usar la compilación de múltiples etapas de Docker
-
Primera etapa de compilación de Docker:
- Descargar e instalar
Oracle OpenJDK
archivo en la primera etapa de compilación de Docker - compile la distribución mínima de Java para su proyecto (también conocido como JRE) usando
jlink
herramienta
- Descargar e instalar
-
Segunda etapa de compilación de Docker:
- copiar la distribución mínima compilada de Java desde la etapa 1 a la nueva imagen
- configurar la ruta para acceder a Java
- copiar el tarro de la aplicación a la imagen
-
Entonces, final
Dockerfile
se ve algo así(actualizar JDK
VERSION
,URL
yHASH
valor):# 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" ]
Nota:
- hay 5 módulos java incluidos en el ejemplo mínimo de JRE (
java.base,java.sql,java.naming,java.desktop,java.management,java.security.jgss,java.instrument
). Los encontré “manualmente” ejecutando la aplicación y arreglandoClassNotFoundException
. Esperando algunas recomendaciones / guías adicionales de los desarrolladores de Spring Boot qué módulos de Java incluir y cuándo, al igual que eliminar algunas dependencias redundantes, comojava.desktop
, que parece usarse solo paraPropertyEditorSupport
-
Si tiene miedo de perder algunos módulos, son bastante livianos y todos juntos aumentan el tamaño de aproximadamente 2 MB. Obtenga una lista completa de
java.*
yjdk.*
11 módulos:java --list-modules | grep -E "^java.[^@]*" | cut -d @ -f 1
java --list-modules | grep -E "^jdk.[^@]*" | cut -d @ -f 1
El tamaño de la imagen resultante en mi caso fue 123 MB con un mínimo de 7 módulos Spring Boot y 125 MB con toda
java.*
modulosComo una mejora opcional de este flujo de trabajo de compilación:
- Construya previamente una imagen con JDK descargado y extraído y utilícela como imagen base para la primera etapa
- si sabe qué módulos incluir cada vez, cree previamente una imagen base con JRE mínimo compilado y módulos incluidos
- usar
-
Manera fácil con distribuciones Open JDK del proveedor:
Frente a Zulu JDK 11 de Oracle Azul es compatible con el puerto Alpine y tiene la imagen de Docker base respectiva.
Por lo tanto, si se respeta Zulu JVM / JDK, la compilación de Docker es mucho más simple:
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" ]
La imagen resultante es 73 MB, como se esperaba con distribuciones de Alpine despojadas.
A 07.2019
(Nota: la imagen de la primera etapa podría ser como grasa como desee: se puede usar debian / ubuntu / lo que sea e incluir git / gradle / lo que sea; esto no influirá en el tamaño final de la imagen resultante, que se basa completamente en la última (segunda) etapa)
Uso del repositorio de la comunidad Alpine
FROM alpine:latest as packager
RUN apk --no-cache add openjdk11-jdk openjdk11-jmods
ENV JAVA_MINIMAL="/opt/java-minimal"
# build minimal JRE
RUN /usr/lib/jvm/java-11-openjdk/bin/jlink
--verbose
--add-modules
java.base,java.sql,java.naming,java.desktop,java.management,java.security.jgss,java.instrument
--compress 2 --strip-debug --no-header-files --no-man-pages
--release-info="add:IMPLEMENTOR=radistao:IMPLEMENTOR_VERSION=radistao_JRE"
--output "$JAVA_MINIMAL"
FROM alpine:latest
ENV JAVA_HOME=/opt/java-minimal
ENV PATH="$PATH:$JAVA_HOME/bin"
COPY --from=packager "$JAVA_HOME" "$JAVA_HOME"
COPY build/libs/application.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
Usando AdoptOpenJDK
FROM adoptopenjdk/openjdk11:x86_64-alpine-jdk-11.0.4_11 as packager
ENV JAVA_MINIMAL="/opt/java-minimal"
# build minimal JRE
RUN jlink
--verbose
--add-modules
java.base,java.sql,java.naming,java.desktop,java.management,java.security.jgss,java.instrument
--compress 2 --strip-debug --no-header-files --no-man-pages
--output "$JAVA_MINIMAL"
FROM alpine:latest
# magic to make Java binaries work in Alpine
# https://github.com/AdoptOpenJDK/openjdk-docker/blob/master/11/jdk/alpine/Dockerfile.hotspot.releases.slim#L24-L54
RUN apk add --no-cache --virtual .build-deps curl binutils
&& GLIBC_VER="2.29-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-9.1.0-2-x86_64.pkg.tar.xz"
&& GCC_LIBS_SHA256="91dba90f3c20d32fcf7f1dbe91523653018aa0b8d2230b00f822f6722804cf08"
&& ZLIB_URL="https://archive.archlinux.org/packages/z/zlib/zlib-1%3A1.2.11-3-x86_64.pkg.tar.xz"
&& ZLIB_SHA256=17aede0b9f8baa789c5aa3f358fbf8c68a5f1228c5e6cba1a5dd34102ef4d4e5
&& curl -LfsS https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub -o /etc/apk/keys/sgerrand.rsa.pub
&& SGERRAND_RSA_SHA256="823b54589c93b02497f1ba4dc622eaef9c813e6b0f0ebbb2f771e32adf9f4ef2"
&& echo "$SGERRAND_RSA_SHA256 */etc/apk/keys/sgerrand.rsa.pub" | sha256sum -c -
&& curl -LfsS $ALPINE_GLIBC_REPO/$GLIBC_VER/glibc-$GLIBC_VER.apk > /tmp/glibc-$GLIBC_VER.apk
&& apk add /tmp/glibc-$GLIBC_VER.apk
&& curl -LfsS $ALPINE_GLIBC_REPO/$GLIBC_VER/glibc-bin-$GLIBC_VER.apk > /tmp/glibc-bin-$GLIBC_VER.apk
&& apk add /tmp/glibc-bin-$GLIBC_VER.apk
&& curl -Ls $ALPINE_GLIBC_REPO/$GLIBC_VER/glibc-i18n-$GLIBC_VER.apk > /tmp/glibc-i18n-$GLIBC_VER.apk
&& apk add /tmp/glibc-i18n-$GLIBC_VER.apk
&& /usr/glibc-compat/bin/localedef --force --inputfile POSIX --charmap UTF-8 "$LANG" || true
&& echo "export LANG=$LANG" > /etc/profile.d/locale.sh
&& curl -LfsS $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 -LfsS $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 --purge .build-deps glibc-i18n
&& rm -rf /tmp/*.apk /tmp/gcc /tmp/gcc-libs.tar.xz /tmp/libz /tmp/libz.tar.xz /var/cache/apk/*
ENV JAVA_HOME=/opt/java-minimal
ENV PATH="$PATH:$JAVA_HOME/bin"
COPY --from=packager "$JAVA_HOME" "$JAVA_HOME"
COPY build/libs/application.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
Lea también https://blog.gilliard.lol/2018/11/05/alpine-jdk11-images.html
una lista de imágenes jdk 11 por tamaño
openjdk:11.0.6-jre-buster
openjdk:11.0.6-jre
openjdk:11.0.6-jre-slim-buster
openjdk:11.0.6-jre-slim
openjdk:11.0.6-jre-stretch
adoptopenjdk:11.0.6_10-jre-openj9-0.18.1
adoptopenjdk:11.0.6_10-jre-hotspot
adoptopenjdk:11.0.6_10-jre-openj9-0.18.1-bionic
adoptopenjdk:11.0.6_10-jre-hotspot-bionic
adoptopenjdk/openjdk11:jre-11.0.6_10-ubuntu
adoptopenjdk/openjdk11:jre-11.0.6_10
adoptopenjdk/openjdk11:jre-11.0.6_10-ubi-minimal
adoptopenjdk/openjdk11:jre-11.0.6_10-ubi
adoptopenjdk/openjdk11:jre-11.0.6_10-debianslim
adoptopenjdk/openjdk11:jre-11.0.6_10-debian
adoptopenjdk/openjdk11:jre-11.0.6_10-centos
adoptopenjdk/openjdk11:jre-11.0.6_10-alpine
adoptopenjdk/openjdk11:x86_64-alpine-jre-11.0.6_10
adoptopenjdk/openjdk11:x86_64-debian-jre-11.0.6_10
adoptopenjdk/openjdk11:x86_64-debianslim-jre-11.0.6_10
adoptopenjdk/openjdk11:x86_64-ubi-jre-11.0.6_10
adoptopenjdk/openjdk11:x86_64-ubi-minimal-jre-11.0.6_10
adoptopenjdk/openjdk11:x86_64-centos-jre-11.0.6_10
adoptopenjdk/openjdk11:x86_64-ubuntu-jre-11.0.6_10
mcr.microsoft.com/java/jre:11u6-zulu-alpine
mcr.microsoft.com/java/jre:11u6-zulu-centos
mcr.microsoft.com/java/jre:11u6-zulu-debian8
mcr.microsoft.com/java/jre:11u6-zulu-debian9
mcr.microsoft.com/java/jre:11u6-zulu-debian10
mcr.microsoft.com/java/jre:11u6-zulu-ubuntu
azul/zulu-openjdk-alpine:11.0.6-jre