В этой статье будет объяснено, как создать наименьший возможный образ Docker с помощью JHipster 6 и Java 11+.
Обязательно сначала прочтите “Лучшую, более быструю и легкую Java с Java 12 и JHipster 6” Мэтта Райбла.
Сегодня (понедельник, 13 мая 2019 года) Мохаммед Абуллайт (из Devoxx Morocco) выступил с потрясающим докладом на тему “Контейнеры Docker и java: Что бы я хотел, чтобы мне сказали!” с большим количеством интересной информации. Не забудьте проверить его слайд-деку.
Вы можете пропустить эту часть, если на вашем компьютере для разработки уже запущена Java 11.
SDKman – отличный инструмент для установки нескольких версий Java. Этот инструмент также позволяет вам очень легко переключаться между различными версиями java. # Должен иметь
После установки вы можете перечислить все доступные версии Java SDK.
$ sdk list java Вы можете выбрать (и установить) версию Java 11 SDK следующим образом:
$ sdk использует java 11.0.3-зулу Теперь мы можем изменить maven pom.xml java.версия от 1.8 до 11.
11
Файлы SDK расположены в скрытом каталоге .sdkman, что немного затрудняет повторное использование в IDEA. Добавление символической ссылки – это прагматичное решение:
$ cd /Library/Java/JavaVirtualMachines $ sudo ln -s /Users/stephan/.sdkman/candidates/java/11.0.3-zulu 11.0.03-zulu
Теперь вы можете добавить SDK 11 к своей ИДЕЕ.
JHipster предоставляет файл Dockerfile, который находится в src/main/docker:
FROM openjdk:11-jre-slim-stretch ENV SPRING_OUTPUT_ANSI_ENABLED=ALWAYS \ JHIPSTER_SLEEP=0 \ JAVA_OPTS="" # Add a jhipster user to run our application so that it doesn't need to run as root RUN adduser -D -s /bin/sh jhipster WORKDIR /home/jhipster ADD entrypoint.sh entrypoint.sh RUN chmod 755 entrypoint.sh && chown jhipster:jhipster entrypoint.sh USER jhipster ENTRYPOINT ["./entrypoint.sh"] EXPOSE 8080 ADD *.war app.war
У меня есть несколько проблем с этим файлом Dockerfile, главная из которых… это не работает 😂
Обязательно прочтите дополнение, почему файл Dockerfile поврежден.
1) Команда adduser выдает ошибку при создании образа Docker.
Option d is ambiguous (debug, disabled-login, disabled-password) Option s is ambiguous (shell, system) adduser [--home DIR] [--shell SHELL] [--no-create-home] [--uid ID] [--firstuid ID] [--lastuid ID] [--gecos GECOS] [--ingroup GROUP | --gid ID] [--disabled-password] [--disabled-login] [--add_extra_groups] USER Add a normal user adduser --system [--home DIR] [--shell SHELL] [--no-create-home] [--uid ID] [--gecos GECOS] [--group | --ingroup GROUP | --gid ID] [--disabled-password] [--disabled-login] [--add_extra_groups] USER Add a system user adduser --group [--gid ID] GROUP addgroup [--gid ID] GROUP Add a user group addgroup --system [--gid ID] GROUP Add a system group adduser USER GROUP Add an existing user to an existing group general options: --quiet | -q don't give process information to stdout --force-badname allow usernames which do not match the NAME_REGEX configuration variable --help | -h usage message --version | -v version number and copyright --conf | -c FILE use FILE as configuration file
Команда ‘/bin/sh -c adduser -D -s/bin/sh jhipster’ вернула ненулевой код: 1
2) Файл Dockerfile должен добавлять файл JAR, а не файл war (см. maven pom.xml поле упаковки файла).
В entrypoint.sh сценарий также должен использовать jar-файл вместо war.
#!/bin/sh echo "The application will start in ${JHIPSTER_SLEEP}s..." && sleep ${JHIPSTER_SLEEP} exec java ${JAVA_OPTS} -noverify -XX:+AlwaysPreTouch -Djava.security.egd=file:/dev/./urandom -jar "${HOME}/app.war" "$@" DockerFile V2 FROM openjdk:11-jre-slim-stretch ENV SPRING_OUTPUT_ANSI_ENABLED=ALWAYS \ JHIPSTER_SLEEP=0 \ JAVA_OPTS="" # Add a jhipster user to run our application so that it doesn't need to run as root RUN adduser --home /home/jhipster --disabled-password jhipster WORKDIR /home/jhipster ADD entrypoint.sh entrypoint.sh RUN chmod 755 entrypoint.sh && chown jhipster:jhipster entrypoint.sh USER jhipster ENTRYPOINT ["./entrypoint.sh"] EXPOSE 8080 ADD *.jar app.jar
Это создает образ Docker размером 340 МБ, но можем ли мы сделать его меньше?
Файл JHipster Dockerfile использует образ среды выполнения OpenJDK 11, основанный на Debian, что частично объясняет, почему размер образа составляет 340 МБ. Переход на Alpine Linux – лучшая стратегия!
Мохаммед из DevoxxMA предложил рассмотреть еще меньшую возможность, используя “Бездисковые” изображения Docker от Google. # Нужно Больше Времени Для Расследования
ПОДСКАЗКА: Подумайте о том, чтобы посмотреть эту очень интересную презентацию Voxxed Days Zurich 2019 от Мэтью Гиллиарда о контейнерах Java. Он берет пример Hello World и развертывает его, используя различные стратегии, включая собственные изображения.
Azul предоставляет дистрибутив Alpine Linux OpenJDK для Java 11, лучшее из обоих миров!
Среда выполнения Azul интегрирует и изначально поддерживает библиотеку musl, что делает интеграцию более эффективной (с точки зрения занимаемой площади и производительности во время выполнения).
Смотрите также проект Portola – Цель этого проекта – предоставить порт JDK для дистрибутива Alpine Linux и, в частности, библиотеки musl C.
Теперь, когда мы (наконец-то) перешли на Java 9+, мы можем воспользоваться преимуществами системы Java modules. Это означает, что мы можем создать пользовательскую JVM, которая включает в себя только модули Java, используемые нашим приложением.
Чтобы выяснить, какие модули используются, мы можем использовать jdeps для самоанализа нашего jar-файла проекта.
$ jdeps --list-deps myapp-1.0.0.jar java.base java.logging java.sql
Похоже, для приложения требуется всего 3 модуля Java. К сожалению, это неверно, подробнее об этом позже.
Следующий шаг – создать пользовательскую JVM с помощью j link и добавить 3 необходимых модуля:
$ jlink --output myjdk --module-path $JAVA_HOME/jmods --add-modules java.base,java.sql,java.logging
Приведенная выше команда создает каталог my jdk, в который включено все необходимое для запуска нашего jar-файла.
После запуска приложения JHipster на рабочей машине я заметил, что для запуска веб-приложения Spring Boot с использованием Java 11 по-прежнему не хватает нескольких модулей.
java.desktop // For Java Beans getter's and setters java.management // JMX jdk.management // JDK-specific management interfaces for the JVM java.naming // JNDI jdk.unsupported // Sun.misc.Unsafe jdk.crypto.ec // SSL java.net.http // HTTP
Очевидно, что в зависимости от функциональности вашего проекта вам потребуется добавить больше модулей.
Теперь, когда мы знаем, какие модули Java требуются, мы можем создать следующий файл Dockerfile.
Часть 1: Возьмите jvm Azul zulu OpenJDK и создайте пользовательскую JVM в каталоге/jlinked.
Часть 2
Используйте Alpine linux и скопируйте связанный JDK в/opt/jdk и запустите java-приложение. Undertow вынудил меня запустить Spring Boot от имени root, потому что в противном случае он мог бы не открывать некоторые сокеты. Необходимо дальнейшее расследование, предложения всегда приветствуются.
# # Part 1 # FROM azul/zulu-openjdk-alpine:11 as zulu RUN export ZULU_FOLDER=`ls /usr/lib/jvm/` \ && jlink --compress=1 --strip-debug --no-header-files --no-man-pages \ --module-path /usr/lib/jvm/$ZULU_FOLDER/jmods \ --add-modules java.desktop,java.logging,java.sql,java.management,java.naming,jdk.unsupported,jdk.management,jdk.crypto.ec,java.net.http \ --output /jlinked # # Part 2 # FROM alpine:latest COPY --from=zulu /jlinked /opt/jdk/ RUN apk update RUN rm -rf /var/cache/apk/* ENV CFP_JAVA_OPTS="-Xmx512m" ENV CFP_PERFORMANCE_OPTS="-Dspring.jmx.enabled=false -Dlog4j2.disableJmx=true" CMD /opt/jdk/bin/java $CFP_JAVA_OPTS $CFP_PERFORMANCE_OPTS -XX:+UseContainerSupport \ -noverify -XX:+AlwaysPreTouch -Djava.security.egd=file:/dev/./urandom -jar /app.jar ADD target/*.jar /app.jar EXPOSE 80
Приведенный выше пример в значительной степени вдохновлен ALF.io предоставленный файл Dockerfile Теперь у нас есть 180-мегабайтный образ Docker, который мы можем развернуть в рабочей среде 😎 💪🏻
В моем списке дел – изучить Общий доступ к данным класса приложений (CDS), при правильной настройке время запуска приложения может быть на 25% быстрее!
CDS была единственной коммерческой функцией Oracle JDK начиная с версии 7, но она также была доступна в OpenJ9 и теперь включена в OpenJDK начиная с версии 10.
Другая стратегия для исследования – использовать разнесенный файл jar, не уверен, что это даст какое-либо заметное увеличение времени запуска?
Абсолютно!
Представьте, что JHipster мог бы создать проект Quark u s и/или Micronaut на основе вашего JDL. Это означало бы, что мы могли бы создать собственный образ благодаря GraalVM.
Создание еще меньшего изображения Docker и потрясающий быстрый запуск … великолепная комбинация с Google Cloud Run!
Комментарии и предложения очень приветствуются!
Овации,
Стефан
Часть 2 этой серии статей теперь доступна @ Часть 2 этой серии статей теперь доступна @
Кливер
Немедленный ответ на мою статью пришел от Кристофа, спасибо за отзыв!
Похоже, что JHipster теперь использует Jib вместо предоставленного Dockerfile. Нужно будет выяснить, как выглядит Dockerfile и предоставляет ли он изображение меньшего размера?!
Jib создает оптимизированные образы Docker и OCI для ваших Java-приложений без демона Docker и без глубокого знания лучших практик Docker. Он доступен в виде плагинов для Maven и Gradle, а также в виде библиотеки Java.
./mvnw package -Pprod verify jib:dockerBuild More details @ https://www.jhipster.tech/docker-compose/#-building-and-running-a-docker-image-of-your-application
Другой ответ на статью сообщил мне, что команда Hipster перешла на OpenJDK 11 с использованием Alpine 3 дня назад. Вот что мне нравится в хипстерах, они на вершине своей игры!
Мой друг из Марокко Devoxx Мохаммед (и чемпион Docker) предложил в ответе в Твиттере взглянуть на изображения docker без дистрибутивов Google. Выглядит действительно очень многообещающе, нужно больше времени для расследования 😄
Spring Boot использует Undertow и зависит от jboss XNIO-NIO. В результате Java 11 выдаст предупреждение: незаконная операция отражающего доступа.
Переключение на причал вместо подводного течения может решить эту проблему?
WARNING: An illegal reflective access operation has occurred [dvbe19-cfp-app-64676889d-4g8nv dvbe19-app] WARNING: Illegal reflective access by org.xnio.nio.NioXnio$2 (jar:file:/app.jar!/BOOT-INF/lib/xnio-nio-3.3.8.Final.jar!/) to constructor sun.nio.ch.EPollSelectorProvider() [dvbe19-cfp-app-64676889d-4g8nv dvbe19-app] WARNING: Please consider reporting this to the maintainers of org.xnio.nio.NioXnio$2 [dvbe19-cfp-app-64676889d-4g8nv dvbe19-app] WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations [dvbe19-cfp-app-64676889d-4g8nv dvbe19-app] WARNING: All illegal access operations will be denied in a future release
И еще одно рефлексивное предупреждение. Но для этого у нас нет альтернативы (пока).
[INFO] --- maven-war-plugin:2.2:war (default-war) @ cfp --- WARNING: An illegal reflective access operation has occurred WARNING: Illegal reflective access by com.thoughtworks.xstream.core.util.Fields (file:/Users/stephan/.m2/repository/com/thoughtworks/xstream/xstream/1.3.1/xstream-1.3.1.jar) to field java.util.Properties.defaults WARNING: Please consider reporting this to the maintainers of com.thoughtworks.xstream.core.util.Fields WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations WARNING: All illegal access operations will be denied in a future release References https://developer.okta.com/blog/2019/04/04/java-11-java-12-jhipster-oidc https://spring.io/blog/2018/12/12/how-fast-is-spring https://blog.gilliard.lol/2018/11/05/alpine-jdk11-images.html https://docs.oracle.com/en/java/javase/11/vm/class-data-sharing.html Docker containers & java: What I wish I've been told! https://docs.google.com/presentation/d/1d2L6O6WELVT6rwwhiw_Z9jBnFzVPtku4URPt4KCsWZQ/edit#slide=id.g5278af057a_0_124 "Docker containers & java: What I wish I've been told!" Video @ https://www.docker.com/dockercon/2019-videos?watch=docker-containers-java-what-i-wish-i-had-been-told
- Но для этого у нас нет альтернативы (пока).
- Но для этого у нас нет альтернативы (пока).
- https://blog.gilliard.lol/2018/11/05/alpine-jdk11-images.html
- https://blog.gilliard.lol/2018/11/05/alpine-jdk11-images.html
- https://blog.gilliard.lol/2018/11/05/alpine-jdk11-images.html
- “Контейнеры Docker и java: О чем бы я хотел, чтобы мне сказали!” Видео @ Видео @
Оригинал: “https://dev.to/stephan007/create-the-smallest-docker-image-using-jhipster-6-and-java-11-35m7”