Docker وKotlin: حاويات التطبيقات على مستوى متقدم
\n\nأصبحت الحاويات جزءًا لا يتجزأ من التطوير الحديث، وKotlin ليست استثناءً. إذا كنت قد أتقنت بالفعل أساسيات Dockerfile وتشغيل ملفات JAR البسيطة، فقد حان الوقت للانتقال إلى المستوى التالي. في هذه المقالة، سنستعرض التقنيات المتقدمة لحاويات تطبيقات Kotlin: البناء متعدد المراحل (multi-stage builds)، تحسين حجم الصور، الإعداد لأطر العمل Ktor وSpring Boot، بالإضافة إلى العمل مع Docker Compose في بيئة الإنتاج.
\n\n1. البناء متعدد المراحل لتطبيقات Kotlin
\n\nإحدى المشكلات الرئيسية عند حاويات تطبيقات JVM هي حجم الصورة النهائية. يمكن أن يزيد وزن صورة OpenJDK القياسية عن 400 ميجابايت. يسمح البناء متعدد المراحل بفصل بيئة البناء عن بيئة التشغيل، باستخدام صورة تشغيل ضئيلة الحجم.
\n\nمثال لمشروع Gradle بلغة Kotlin
\n\n# المرحلة الأولى: البناء\nFROM gradle:8.5-jdk21 AS builder\nWORKDIR /app\nCOPY build.gradle.kts settings.gradle.kts ./\nCOPY src ./src\nRUN gradle build --no-daemon -x test\n\n# المرحلة الثانية: التشغيل\nFROM eclipse-temurin:21-jre-alpine\nWORKDIR /app\nCOPY --from=builder /app/build/libs/app.jar app.jar\nEXPOSE 8080\nENTRYPOINT ["java", "-jar", "app.jar"]\n\nاستخدام eclipse-temurin:21-jre-alpine بدلاً من صورة JDK الكاملة يقلل الحجم من 400+ ميجابايت إلى حوالي 120 ميجابايت. وهذا أكثر من كافٍ لتطبيقات Kotlin على Ktor أو Spring Boot.
تحسين التخزين المؤقت للطبقات
\n\nلتسريع عمليات البناء المتكررة، انسخ التبعيات بشكل منفصل عن الكود المصدري:
\n\nFROM gradle:8.5-jdk21 AS builder\nWORKDIR /app\n# أولاً التبعيات (يتم تخزينها مؤقتًا إذا لم تتغير)\nCOPY build.gradle.kts settings.gradle.kts ./\nRUN gradle dependencies --no-daemon\n# ثم الملفات المصدرية\nCOPY src ./src\nRUN gradle build --no-daemon -x test\n\nهذه التقنية مفيدة بشكل خاص في CI/CD، حيث كل ثانية لها أهميتها.
\n\n2. تحسين الصور لتطبيقات Kotlin
\n\nبالإضافة إلى اختيار الصورة الأساسية، هناك تقنيات إضافية لتقليل الحجم وزيادة الأمان.
\n\nاستخدام JLink لإنشاء JRE مخصصة
\n\nإذا كان تطبيقك يستخدم فقط جزءًا من وحدات JDK، يمكنك إنشاء JRE ضئيلة الحجم:
\n\n# في مرحلة البناء\nRUN jlink --module-path /opt/java/openjdk/jmods \\\n --add-modules java.base,java.logging,java.naming,java.sql \\\n --output /custom-jre \\\n --strip-debug --no-man-pages --no-header-files\n\n# في مرحلة التشغيل\nFROM alpine:3.19\nCOPY --from=builder /custom-jre /opt/jre\nCOPY --from=builder /app/build/libs/app.jar /app/app.jar\nENV PATH="/opt/jre/bin:${PATH}"\nEXPOSE 8080\nCMD ["java", "-jar", "/app/app.jar"]\n\nيمكن أن ينخفض حجم الصورة إلى 50-70 ميجابايت.
\n\nالهندسة متعددة الطبقات مع Spring Boot
\n\nيدعم Spring Boot 3+ تقسيم ملف JAR الضخم إلى طبقات. استخدم ذلك في Dockerfile:
\n\nFROM eclipse-temurin:21-jre-alpine AS builder\nWORKDIR /app\nCOPY build/libs/*.jar app.jar\nRUN java -Djarmode=layertools -jar app.jar extract\n\nFROM eclipse-temurin:21-jre-alpine\nWORKDIR /app\nCOPY --from=builder /app/dependencies/ ./\nCOPY --from=builder /app/spring-boot-loader/ ./\nCOPY --from=builder /app/snapshot-dependencies/ ./\nCOPY --from=builder /app/application/ ./\nENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"]\n\nالآن عند تغيير الكود، يتم إعادة بناء طبقة application فقط، بينما تبقى التبعيات ومُحمل Spring Boot مخزنة مؤقتًا.
3. حاويات تطبيقات Ktor
\n\nKtor هو إطار عمل خفيف لإنشاء خوادم غير متزامنة بلغة Kotlin. حاوياته لها خصائصها الخاصة.
\n\nDockerfile لـ Ktor مع Netty
\n\nFROM gradle:8.5-jdk21 AS builder\nWORKDIR /app\nCOPY build.gradle.kts settings.gradle.kts ./\nRUN gradle dependencies --