Docker وKotlin: حاويات التطبيقات المتقدمة

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

Docker وKotlin: حاويات التطبيقات المتقدمة



أصبحت الحاويات جزءًا لا يتجزأ من التطوير الحديث. إذا كنت قد أتقنت بالفعل المبادئ الأساسية لـ Docker وكتبت بعض الصور البسيطة باستخدام Kotlin، فقد حان الوقت للانتقال إلى المستوى التالي. في هذه المقالة، سنستعرض التقنيات المتقدمة: البناء متعدد المراحل، تحسين حجم الصورة النهائية، العمل مع الأطر الشائعة (Ktor, Spring Boot)، والإدارة الفعالة للـ coroutines في بيئة الحاويات.



1. البناء متعدد المراحل (Multi-stage builds)



إحدى المشكلات الرئيسية عند حاويات تطبيقات JVM هي حجم الصورة. يمكن أن تزن صورة JDK الأساسية مئات الميغابايت. يسمح البناء متعدد المراحل بفصل مراحل التجميع والتنفيذ، مع ترك JRE و JAR المجمّع فقط في الصورة النهائية.



لنلقِ نظرة على مثال لتطبيق Kotlin يتم بناؤه باستخدام Gradle:



# مرحلة البناءFROM gradle:7.6-jdk17 AS builderWORKDIR /appCOPY build.gradle.kts settings.gradle.kts ./COPY src ./srcRUN gradle build --no-daemon -x test

# مرحلة التنفيذFROM eclipse-temurin:17-jre-alpineWORKDIR /appCOPY --from=builder /app/build/libs/*.jar app.jarEXPOSE 8080CMD ["java", "-jar", "app.jar"]


لماذا هذا فعال؟

  • في مرحلة البناء، يتم استخدام JDK و Gradle كاملين، لكنهما لا يدخلان في الصورة النهائية.
  • تحتوي الصورة النهائية على JRE (Java Runtime Environment) فقط، مما يقلل الحجم بمقدار 3-5 مرات.
  • يعمل Alpine Linux على تقليل الحجم إلى حوالي 150-200 ميجابايت بدلاً من 600+ ميجابايت.


2. تحسين الطبقات والتخزين المؤقت



يقوم Docker بتخزين الطبقات مؤقتًا، ولكن فقط إذا لم تتغير. لتسريع عمليات البناء المتكررة، قم بفصل التبعيات والكود المصدري:



FROM gradle:7.6-jdk17 AS builderWORKDIR /app

# أولاً، انسخ ملفات التبعيات فقطCOPY build.gradle.kts settings.gradle.kts ./RUN gradle dependencies --no-daemon

# ثم الكود المصدري (يتغير بشكل متكرر)COPY src ./srcRUN gradle build --no-daemon -x test


يضمن هذا النهج إعادة بناء طبقة التبعيات فقط عند تغيير build.gradle.kts. بخلاف ذلك، يستخدم Docker ذاكرة التخزين المؤقت، مما يوفر دقائق في كل تكرار.



نصيحة: بالنسبة لمشاريع Kotlin التي تحتوي على عدد كبير من التبعيات (مثل Spring Boot)، تكون هذه التقنية ذات صلة خاصة — يمكن أن يستغرق تحميل ذاكرة التخزين المؤقت لـ Gradle ما يصل إلى 2-3 دقائق.



3. حاويات تطبيقات Ktor



Ktor هو إطار عمل غير متزامن خفيف الوزن بلغة Kotlin، مثالي للخدمات المصغرة. تتطلب حاويات تطبيق Ktor الحد الأدنى من الإعداد، ولكن هناك فروق دقيقة تتعلق بالـ coroutines.



مثال على Dockerfile لـ Ktor:



FROM gradle:7.6-jdk17 AS builderWORKDIR /appCOPY build.gradle.kts settings.gradle.kts ./RUN gradle dependencies --no-daemonCOPY src ./srcRUN gradle build --no-daemon -x test

FROM eclipse-temurin:17-jre-alpineWORKDIR /appCOPY --from=builder /app/build/libs/ktor-app-*.jar app.jarEXPOSE 8080

# مهم: إعداد JVM للـ coroutinesCMD ["java", "-XX:+UseZGC", "-Xms256m", "-Xmx512m", "-jar", "app.jar"]


النقاط الرئيسية:

  • استخدم ZGC (Z Garbage Collector) — فهو يقلل من فترات التوقف، وهو أمر بالغ الأهمية للتطبيقات غير المتزامنة التي تحتوي على عدد كبير من الـ coroutines.
  • حدد الذاكرة من خلال -Xms و -Xmx. في الحاويات، يساعد ذلك في تجنب أخطاء OOM.
  • تأكد من أن خادم Ktor لا يحظر الخيط الرئيسي — يجب تكوين الـ coroutines من خلال Dispatchers.IO أو مجموعة مخصصة.


مثال على إعداد Ktor للعمل في حاوية:



fun main() {    embeddedServer(Netty, port = 8080, host = "0.0.0.0") {        routing {            get("/") {                

المدونات

توصيات الكتب