مقدمة إلى Docker وJava: لماذا تغير الحاوية طريقة التطوير
تطوير البرمجيات الحديث لا يمكن تصوره بدون الحاويات. أصبح Docker المعيار الفعلي لتغليف التطبيقات وتسليمها وتشغيلها. بالنسبة لمطوري Java، يحل استخدام Docker المشكلات الرئيسية: "هذا يعمل على جهازي" وصعوبات إعداد البيئة. في هذه المقالة، سنشرح كيفية حاويات تطبيقات Java، من ملف JAR بسيط إلى خدمة مصغرة معقدة على Spring Boot.
يسمح Docker بعزل التطبيق مع تبعياته (JVM، المكتبات، الأدوات النظامية) في حاوية خفيفة الوزن وقابلة للنقل. هذا مهم بشكل خاص لـ Java، حيث يمكن أن تؤثر إصدارات JDK وإعدادات الذاكرة والمكتبات النظامية بشكل كبير على سلوك البرنامج.
ما ستتعلمه من هذه المقالة
- إنشاء Dockerfile لتطبيقات Java
- تحسين أحجام الصور
- العمل مع مشاريع Maven/Gradle متعددة الوحدات
- أفضل ممارسات الأمان والأداء
1. الأساسيات: إنشاء Dockerfile لتطبيق Java
لنبدأ بمثال بسيط. افترض أن لديك تطبيق Java تم تجميعه في ملف JAR. إليك Dockerfile الأدنى الذي سيحزمه في حاوية:
# نستخدم الصورة الرسمية لـ OpenJDKFROM openjdk:17-jdk-slim
# نحدد دليل العملWORKDIR /app
# ننسخ ملف JAR إلى الحاويةCOPY target/myapp.jar app.jar
# نفتح المنفذ الذي يستمع إليه التطبيقEXPOSE 8080
# الأمر للتشغيلENTRYPOINT ["java", "-jar", "app.jar"]يقوم هذا Dockerfile بثلاثة أشياء بسيطة: يأخذ صورة أساسية مع JDK 17، ينسخ JAR المترجم، ويشغله. ومع ذلك، في المشاريع الحقيقية، هذا الأسلوب غير فعال - في كل مرة يتغير فيها الكود، يعيد Docker بناء الصورة بأكملها، بما في ذلك نسخ JAR.
البناء متعدد المراحل (Multi-stage build)
لفصل مراحل البناء والتنفيذ، استخدم Dockerfile متعدد المراحل. هذا يقلل من الصورة النهائية عن طريق استبعاد أدوات البناء (Maven، Gradle، JDK للترجمة).
# مرحلة البناءFROM maven:3.9.6-eclipse-temurin-17 AS builderWORKDIR /buildCOPY pom.xml .RUN mvn dependency:go-offlineCOPY src ./srcRUN mvn clean package -DskipTests
# المرحلة النهائيةFROM openjdk:17-jdk-slimWORKDIR /appCOPY --from=builder /build/target/*.jar app.jarEXPOSE 8080ENTRYPOINT ["java", "-jar", "app.jar"]تستخدم المرحلة الأولى صورة Maven الكاملة للترجمة، والثانية تستخدم صورة JRE الحد الأدنى للتشغيل. تزن الصورة النهائية حوالي 200 ميجابايت بدلاً من 700+ ميجابايت.
2. تحسين الصور: تقليل الحجم وتسريع البناء
الصور الكبيرة تبطئ النشر وتزيد وقت التحميل. إليك بعض التقنيات لـ Java:
استخدم JLink لإنشاء JRE الحد الأدنى
بدءًا من Java 9، يمكنك إنشاء JRE مخصص يحتوي فقط على الوحدات الضرورية. هذا يقلل حجم الصورة بشكل جذري.
FROM openjdk:17-jdk-slim AS jre-builderRUN jlink \ --add-modules java.base,java.logging,java.sql \ --strip-debug \ --no-man-pages \ --no-header-files \ --compress=2 \ --output /jre
FROM debian:bookworm-slimCOPY --from=jre-builder /jre /jreWORKDIR /appCOPY target/myapp.jar app.jarENV PATH="/jre/bin:${PATH}"ENTRYPOINT ["java", "-jar", "app.jar"]يمكن أن تزن هذه الصورة 40-60 ميجابايت فقط بدلاً من 200+ ميجابايت.
تخزين طبقات Docker مؤقتًا
يقوم Docker بتخزين كل طبقة مؤقتًا. لتسريع البناء، ضع الملفات التي نادرًا ما تتغير (التبعيات) في بداية Dockerfile، والملفات التي تتكرر تغييراتها (الكود المصدري) في النهاية.
FROM maven:3.9.6-eclipse-temurin-17 AS builderWORKDIR /build# أولاً ننسخ فقط pom.xml ونحمل التبعياتCOPY pom.xml .RUN mvn dependency:go-offline# ثم ننسخ المصادر ونجمعCOPY src ./srcRUN mvn clean packag