تخطَّ إلى المحتوى

🐳 شرح Docker

Docker Compose: حاويات تهيئة الخدمة (pre_start)

الدرس 30 من 31· ⏱ 2 دقائق قراءة· 🗓 آخر تحديث: ٣١ أغسطس ٢٠٢٦

المشكلة: تحضير لازم قبل إقلاع الخدمة

في درس تطبيق متعدّد الحاويات تعرّفت على depends_on — لكن لاحظنا هناك أنه يضبط ترتيب البدء فقط، لا جاهزية الخدمة. فماذا لو احتجت فعليًا تنفيذ خطوة تحضيرية (تشغيل migration لقاعدة البيانات، انتظار توفّر خدمة خارجية، توليد ملف إعداد) قبل أن تبدأ الخدمة نفسها؟

الحل التقليدي كان تعريف خدمة منفصلة كاملة في compose.yaml تُنفّذ المهمة وتخرج، ثم تجعل خدمتك الأساسية تنتظرها بـ:

services:
  migrate:
    build: .
    command: npm run migrate
  app:
    build: .
    depends_on:
      migrate:
        condition: service_completed_successfully

يعمل هذا الأسلوب، لكن يحمّلك عبء تعريف خدمة كاملة (بصورتها الخاصة، وربما شبكتها) فقط لأجل خطوة تحضير واحدة سريعة.

الحل المدمج: pre_start

Docker Compose أضاف مفتاح pre_start ضمن تعريف الخدمة نفسها: سلسلة خطوات تهيئة تُنفَّذ في حاويات مؤقّتة منفصلة قبل أن تُقلَع حاوية الخدمة الرئيسية — دون الحاجة لتعريف خدمة كاملة إضافية بالملف.

services:
  app:
    build: .
    pre_start:
      - command: npm run migrate
      - command: ["sh", "-c", "until nc -z redis 6379; do sleep 1; done"]
        image: busybox
    command: npm start

الصياغة: command إلزامي، image اختياري

كل خطوة تحت pre_start تقبل command (إلزامي) — الأمر الذي يُنفَّذ. أما image فاختياري: لو أغفلته تستخدم الخطوة صورة الخدمة نفسها تلقائيًا (مناسب لخطوات تعتمد على أدوات مشروعك، كـ migration). لو احتجت أداة مختلفة تمامًا (مثل busybox لفحص جاهزية منفذ شبكة) حدّد image صراحةً كما بالمثال أعلاه.

آلية التنفيذ

  • كل خطوة تُنفَّذ في حاوية مؤقّتة منفصلة خاصة بها، لا داخل حاوية الخدمة الرئيسية.
  • الخطوات تُنفَّذ بالترتيب المُعلَن تسلسليًا — الخطوة التالية لا تبدأ قبل نجاح سابقتها.
  • حاوية الخدمة الرئيسية لا تُقلَع إطلاقًا إلا بعد خروج كل خطوة بكود 0 (نجاح). أي خطوة تخرج بكود غير صفري توقف إقلاع الخدمة وكل ما يعتمد عليها عبر depends_on.

💡 لو خطوة pre_start نجحت سابقًا بنفس تعريفها بالضبط، Compose لا يعيد تنفيذها عند up تالية ولا عند إعادة تشغيل الحاوية بموجب restart — فقط تعريف تغيّر فعليًا يُعاد تشغيله.

⚠️ pre_start تختلف جوهريًا عن depends_on مع condition: service_completed_successfully: الأولى خطوة تهيئة مملوكة لنفس الخدمة بلا تعريف خدمة منفصلة، والثانية تنسيق بين خدمتين مستقلّتين بالملف. اختر pre_start لخطوة تحضير بسيطة تخص خدمة واحدة، واحتفظ بالخدمة المنفصلة لو احتجت هذه الخطوة نفسها من خدمات أخرى أو أردت مراقبتها ككيان مستقل بـ docker compose ps.

هل يحتاج مشروعي هذا فعليًا؟

الحالةالأنسب
خطوة تحضير سريعة تخص خدمة واحدة فقط (migration، انتظار منفذ)pre_start
خطوة تحضير تريد مراقبتها/إعادة استخدامها من عدّة خدماتخدمة منفصلة + depends_on مع condition
فحص استمراري لصحة الخدمة بعد إقلاعهاHEALTHCHECK (راجع مرجع HEALTHCHECK) — مختلف تمامًا عن pre_start الذي يعمل قبل الإقلاع مرّة واحدة

🎯 التالي: خلاصة مسار Docker

شرح Docker Compose: حاويات تهيئة الخدمة (pre_start) — Docker بالعربي
Docker Compose: حاويات تهيئة الخدمة (pre_start)Docker بالعربي · The Code Fix

📚 لمزيد من التعمّق في Docker، راجِع التوثيق الرسمي لـ Docker.

هل كان هذا الدرس مفيدًا؟