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

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

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

ابدأ الدورة

Docker وJava: المستوى المتقدم لحاويات التطبيقات

\n\n

أصبحت حاويات تطبيقات Java المعيار الفعلي في التطوير الحديث. ومع ذلك، فإن المعرفة الأساسية بـ Docker (إنشاء صورة من openjdk:11 وتشغيل الحاوية) لم تعد تلبي متطلبات بيئات الإنتاج. على المستوى المتقدم، من الضروري مراعاة خصائص عمل JVM داخل الحاوية، وتحسين حجم الصور، وإدارة الذاكرة، وإعداد المراقبة. في هذه المقالة، سنستعرض التقنيات الرئيسية التي ستساعدك في إنشاء صور Docker فعالة وآمنة لتطبيقات Java.

\n\n

1. البناء متعدد المراحل: تقليل حجم الصورة

\n\n

النهج التقليدي "ملف Dockerfile واحد - صورة واحدة" غالباً ما يؤدي إلى تضخم الأداة النهائية. تدخل أدوات البناء (Maven, Gradle, المترجم) في الصورة، وهي غير ضرورية في وقت التشغيل. الحل هو البناء متعدد المراحل (multi-stage). نقوم بتقسيم العملية إلى مراحل: البناء (build) والتنفيذ (runtime).

\n\n

مثال على Dockerfile لتطبيق Spring Boot باستخدام Maven:

\n\n
# مرحلة البناء\nFROM maven:3.8.6-openjdk-17 AS builder\nWORKDIR /app\nCOPY pom.xml .\nRUN mvn dependency:go-offline -B\nCOPY src ./src\nRUN mvn clean package -DskipTests\n\n# مرحلة التنفيذ\nFROM eclipse-temurin:17-jre-alpine\nWORKDIR /app\nCOPY --from=builder /app/target/*.jar app.jar\nEXPOSE 8080\nENTRYPOINT ["java", "-jar", "app.jar"]
\n\n

نتيجة لذلك، تزن الصورة النهائية حوالي 150 ميجابايت بدلاً من 600+ ميجابايت. مهم: استخدم صور jre (وليس jdk) والتوزيعات الأصغر (Alpine, Slim). للتطبيقات على Java 17+، يمكنك التفكير في jlink - إنشاء JRE مخصصة فقط بالوحدات الضرورية.

\n\n

2. إعداد JVM للعمل داخل الحاوية

\n\n

لفترة طويلة، لم تكن JVM قادرة على تحديد حدود الذاكرة ووحدة المعالجة المركزية (CPU) المحددة للحاوية بشكل صحيح. بدءاً من Java 8u191 وJava 10، ظهر دعم cgroups v1 (ومع Java 15، cgroups v2). ومع ذلك، لا ينبغي الاعتماد فقط على الأتمتة.

\n\n

المعلمات الرئيسية للإنتاج:

\n
    \n
  • -XX:+UseContainerSupport - تفعيل دعم الحاويات (نشط افتراضياً في Java 10+).
  • \n
  • -XX:MaxRAMPercentage=75.0 - يحد من استخدام الكومة إلى 75% من الذاكرة المتاحة للحاوية. هذا يترك ذاكرة للميتاسبيس، ومكدس الخيوط، والعمليات النظامية.
  • \n
  • -XX:ActiveProcessorCount=2 - تحديد صريح لعدد المعالجات المتاحة، إذا فشل الاكتشاف التلقائي.
  • \n
\n\n

مثال على أمر ENTRYPOINT كامل:

\n\n
ENTRYPOINT ["java", \\\n    "-XX:+UseContainerSupport", \\\n    "-XX:MaxRAMPercentage=75.0", \\\n    "-XX:+ExitOnOutOfMemoryError", \\\n    "-jar", "app.jar"]
\n\n

هام: تجنب القيم الثابتة -Xmx و -Xms في بيئة Docker. فهي لا تتكيف مع تغييرات حدود الحاوية عند التكرار أو التوسع.

\n\n

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

\n\n

كل تعليمة في Dockerfile تنشئ طبقة جديدة. يقوم Docker بتخزين الطبقات التي لم تتغير. لتسريع عمليات البناء المتكررة، رتب التعليمات من الأقل تغيراً إلى الأكثر تغيراً.

\n\n

الهيكل الصحيح لـ Dockerfile:

\n
    \n
  1. تثبيت تبعيات نظام التشغيل (apk add, apt-get).
  2. \n
  3. نسخ ملفات تكوين أداة البناء (pom.xml, build.gradle).
  4. \n
  5. تحميل التبعيات (mvn dependency:go-offline).
  6. \n
  7. نسخ الكود المصدري.
  8. \n
  9. البناء ونسخ الأداة النهائية.
  10. \n
\n\n

بالإضافة إلى ذلك، يمكنك استخدام التخزين المؤقت لطبقات Docker في CI/CD. على سبيل المثال، في GitHub Actions أو GitLab CI، احفظ ذاكرة التخزين المؤقت لـ Maven بين عمليات البناء:

\n\n
# مثال لـ GitLab CI\ncache:\n  key: ${CI_COMMIT_REF_SLUG}\n  paths:\n    - .m2/repository/\n    - .gradle/caches/
\n\n

أيضاً، فكر في استخدام

المدونات

توصيات الكتب