تقليل حجم صورة عامل ميناء مع تطبيق التمهيد الربيع

مساء الخير


في الآونة الأخيرة ، واجهت مهمة تشغيل تطبيقات spring boot 2 في كتلة kubernetes باستخدام صورة عامل ميناء. هذه المشكلة ليست جديدة ، فقد وجدت بسرعة أمثلة في Google وحزمت طلبي. لقد فوجئت جدًا بعدم العثور على صورة جبال الألب لـ jdk11 وآمل أن تكون النحافة صغيرة بما يكفي ، لكن عندما أرسلت الصورة إلى سجل عامل الميناء ، لاحظت أن حجمها كان حوالي 422 ميغابايت. يوجد أسفل القطة وصف للكيفية التي قمت بها بتقليل صورة عامل الإرساء باستخدام إقلاع الربيع وجافا 11 إلى 144 ميغابايت.



تطبيق


كما ذكرت سابقًا ، تم إنشاء تطبيقي باستخدام برنامج spring boot 2 وهو عبارة عن مجمِّع REST API عبر قاعدة بيانات علائقية (باستخدامRepositoryRestResource). تشمل تبعياتي ما يلي:


org.springframework.boot:spring-boot-starter-data-rest org.springframework.boot:spring-boot-starter-data-jpa org.flywaydb:flyway-core org.postgresql:postgresql 

يبلغ حجم ملف الجرة الذي تم جمعه 37.6 ميغابايت.


Dockerfile:


 FROM openjdk:11-jdk-slim WORKDIR /home/demo ARG REVISION COPY target/spring-boot-app-${REVISION}.jar app.jar ENTRYPOINT ["java","-jar","app.jar"] 

كنتيجة للتجميع ، أحصل على صورة بالحجم: 422 ميغابايت وفقًا لإخراج الأمر docker images. ومن المثير للاهتمام ، عند استخدام الصورة التي عفا عليها الزمن 8-jdk-slim ، يتم تقليل الحجم إلى 306 ميغابايت.


محاولة 1: صورة أساسية أخرى


كانت الخطوة المنطقية الأولى هي محاولة للعثور على صورة أكثر وزنًا خفيفًا ، ويفضل أن تستند إلى جبال الألب. قمت بمسح مستودعات جافا الأكثر شعبية:



(11 كإصدار LTS الحالي و 8 حيث لا يزال هناك عدد كاف من التطبيقات التي لا يمكن ترحيلها إلى إصدارات أكثر حداثة)


جدول به صور وعلامات (~ 2700) ، تتوفر أحجامها وقت الكتابة هنا


هؤلاء بعض منهم:


 openjdk 8 488MB openjdk 8-slim 269MB openjdk 8-alpine 105MB openjdk 8-jdk-slim 269MB openjdk 8-jdk-alpine 105MB openjdk 8-jre 246MB openjdk 8-jre-slim 168MB openjdk 8-jre-alpine 84.9MB openjdk 11 604MB openjdk 11-slim 384MB openjdk 11-jdk 604MB openjdk 11-jdk-slim 384MB openjdk 11-jre 479MB openjdk 11-jre-slim 273MB adoptopenjdk/openjdk8 alpine 221MB adoptopenjdk/openjdk8 alpine-slim 89.7MB adoptopenjdk/openjdk8 jre 200MB adoptopenjdk/openjdk8 alpine-jre 121MB adoptopenjdk/openjdk11 alpine 337MB adoptopenjdk/openjdk11 alpine-slim 246MB adoptopenjdk/openjdk11 jre 218MB adoptopenjdk/openjdk11 alpine-jre 140MB 

وبالتالي ، إذا قمت بتغيير الصورة الأساسية إلىoptopenjdk / openjdk11: alpine-jre ، يمكنك تقليل الصورة مع التطبيق إلى 177 ميغابايت.


محاولة 2: وقت التشغيل المخصص


منذ إصدار jdk9 و modularization ، أصبح من الممكن إنشاء وقت التشغيل الخاص بك الذي يحتوي فقط على الوحدات النمطية الضرورية لتطبيقك. يمكنك قراءة المزيد حول هذه الوظيفة هنا .


دعنا نحاول تحديد الوحدات اللازمة لتطبيق اختبار التمهيد الربيع:


 ~/app ᐅ jdeps -s target/app-1.0.0.jar app-1.0.0.jar -> java.base app-1.0.0.jar -> java.logging app-1.0.0.jar -> not found 

حسنًا ، يبدو أن jdeps لا يمكنه التعامل مع جرة fat التي تم إنشاؤها باستخدام برنامج spring spring ، ولكن يمكننا فك ضغط الأرشيف وكتابة classpath:


 ~/app ᐅ jdeps -s -cp target/app-1.0.0/BOOT-INF/lib/*.jar target/app-1.0.0.jar.original Error: byte-buddy-1.9.12.jar is a multi-release jar file but --multi-release option is not set ~/app ᐅ jdeps -s --multi-release 11 -cp target/app-1.0.0/BOOT-INF/lib/*.jar target/app-1.0.0.jar.original Error: aspectjweaver-1.9.2.jar is not a multi-release jar file but --multi-release option is set 

في هذه المناسبة ، يوجد خطأ مفتوح حاليًا: https://bugs.openjdk.java.net/browse/JDK-8207162


لقد حاولت تنزيل jdk12 للحصول على هذه المعلومات ، ولكن واجهت الخطأ التالي:


 Exception in thread "main" com.sun.tools.classfile.Dependencies$ClassFileError ... Caused by: com.sun.tools.classfile.ConstantPool$InvalidEntry: unexpected tag at #1: 53 

بالتجربة والخطأ والبحث عن الوحدة النمطية بواسطة ClassNotFoundException ، قررت أن طلبي يحتاج إلى الوحدات التالية:


  • java.base
  • java.logging
  • java.sql
  • java.naming
  • java.management
  • java.instrument
  • java.desktop
  • java.security.jgss

يمكن جمع وقت التشغيل لهم باستخدام:


 jlink --no-header-files --no-man-pages --compress=2 --strip-debug --add-modules java.base,java.logging,java.sql,java.naming,java.management,java.instrument,java.desktop,java.security.jgss --output /usr/lib/jvm/spring-boot-runtime 

دعنا نحاول بناء صورة لرسو السفن الأساسية باستخدام هذه الوحدات:


 FROM openjdk:11-jdk-slim RUN jlink --no-header-files --no-man-pages --compress=2 --strip-debug --add-modules java.base,java.logging,java.sql,java.naming,java.management,java.instrument,java.desktop,java.security.jgss --output /usr/lib/jvm/spring-boot-runtime FROM debian:stretch-slim COPY --from=0 /usr/lib/jvm/spring-boot-runtime /usr/lib/jvm/spring-boot-runtime RUN ln -s /usr/lib/jvm/spring-boot-runtime/bin/java /usr/bin/java 

وجمعها:


 docker build . -t spring-boot-runtime:openjdk-11-slim 

كنتيجة لذلك ، كان الحجم 106 ميجابايت ، وهو أصغر بكثير من معظم الصور الأساسية التي تم العثور عليها باستخدام openjdk. إذا كنت تستخدمه للتطبيق الخاص بي ، فسيكون الحجم الناتج 144 ميغا بايت.


علاوة على ذلك ، يمكننا استخدام spring-boot-runtime:openjdk-11-slim كصورة أساسية لجميع تطبيقات الإقلاع في الربيع إذا كانت لديها تبعيات مماثلة. في حالة التبعيات المختلفة ، من الممكن استخدام مجموعة صور متعددة المراحل لكل من التطبيقات حيث سيتم جمع وقت تشغيل java في المرحلة الأولى ، وسيتم إضافة الأرشيف مع التطبيق في الثانية.


 FROM openjdk:11-jdk-slim RUN jlink --no-header-files --no-man-pages --compress=2 --strip-debug --add-modules java.base,YOUR_MODULES --output /usr/lib/jvm/spring-boot-runtime FROM debian:stretch-slim COPY --from=0 /usr/lib/jvm/spring-boot-runtime /usr/lib/jvm/spring-boot-runtime WORKDIR /home/demo ARG REVISION COPY target/app-${REVISION}.jar app.jar ENTRYPOINT ["/usr/lib/jvm/spring-boot-runtime/bin/java","-jar","app.jar"] 

استنتاج


حاليًا ، تحتوي معظم صور مرسى java على وحدة تخزين كبيرة بما يكفي ، مما قد يؤثر سلبًا على وقت بدء التطبيق ، خاصة إذا لم تكن الطبقات اللازمة موجودة على الخادم بعد. باستخدام العلامات مع jre أو باستخدام java modularization ، يمكنك إنشاء وقت التشغيل الخاص بك ، مما يقلل بشكل كبير من حجم صورة التطبيق.

Source: https://habr.com/ru/post/ar457476/


All Articles