ما هو Docker Compose؟ ولماذا نحتاجه لتشغيل المشاريع المعقدة؟
ما هو Docker Compose؟ ولماذا نحتاجه لتشغيل المشاريع المعقدة؟
عندما يبدأ المطور باستخدام Docker لأول مرة، يبدو تشغيل حاوية واحدة أمراً بسيطاً وواضحاً. لكن الواقع العملي في المشاريع الحديثة نادراً ما يعتمد على خدمة واحدة فقط. غالباً ما نجد تطبيقاً يتكون من واجهة أمامية، وواجهة خلفية، وقاعدة بيانات، وطبقة تخزين مؤقت، وربما أدوات مراقبة أو بوابة عكسية مثل Nginx.
هنا تظهر الحاجة إلى Docker Compose كأداة تنسيق وتشغيل متعددة الحاويات عبر ملف واحد قابل للإدارة والمراجعة والنسخ. وإذا كنت قد قرأت سابقاً مقال مشكلة “الكود يعمل على جهازي فقط” وكيف يحلها Docker نهائياً؟ فستدرك أن الخطوة التالية من النضج الهندسي ليست فقط عزل التطبيق، بل أيضاً توحيد طريقة تشغيل جميع خدماته التابعة.
ما هو Docker Compose من الناحية الهندسية؟
Docker Compose هو أداة تسمح لك بوصف وتشغيل عدة حاويات مترابطة باستخدام ملف تعريف واحد غالباً باسم compose.yaml أو docker-compose.yml. هذا الملف يحدد الخدمات، المنافذ، الشبكات، المجلدات المشتركة، المتغيرات البيئية، وسياسات إعادة التشغيل.
بدلاً من كتابة سلسلة طويلة من أوامر docker run لكل خدمة، يمكنك تعريف البنية كاملة ثم تشغيلها بأمر واحد. هذا يجعل البيئة قابلة للتكرار بين أجهزة المطورين، وبيئات الاختبار، وحتى مراحل الدمج داخل أنظمة CI/CD.
لفهم الأساسيات التي سبقت هذه المرحلة، يفيد الرجوع إلى مقال أوامر Docker الأساسية للتحكم: تشغيل، إيقاف، فحص، وحذف الحاويات لأن Compose لا يلغي مفاهيم دوكر الأساسية، بل يبني فوقها طبقة تنظيمية أعلى.
لماذا لا تكفي أوامر Docker المنفردة في المشاريع المعقدة؟
في مشروع بسيط قد تتمكن من تشغيل تطبيق Node.js مع قاعدة بيانات PostgreSQL باستخدام أوامر يدوية. لكن مع الوقت ستظهر مشكلات تشغيلية متكررة:
- صعوبة تذكر جميع الأوامر والمعاملات الدقيقة لكل حاوية.
- اختلاف أسماء الشبكات والمنافذ بين جهاز وآخر.
- نسيان إنشاء
volumeدائم للبيانات. - تعقيد ترتيب الإقلاع بين الخدمات المرتبطة ببعضها.
- صعوبة دمج نفس البيئة داخل خطوط
Pipelines.
لهذا السبب يُعد Docker Compose انتقالاً مهماً من الاستخدام الفردي إلى التفكير المعماري. وهو قريب جداً من فلسفة ما هو DevOps؟ ولماذا تدفع الشركات ثروات لمهندسي الأتمتة السحابية؟ حيث تتحول إجراءات التشغيل إلى تعريفات قابلة للأتمتة والمراجعة.
كيف يعمل ملف Compose عملياً؟
يعتمد Compose على صيغة YAML لوصف الخدمات. كل خدمة يمكن أن تُبنى من Dockerfile محلي أو تسحب صورة جاهزة من السجل. إذا كنت تحتاج إلى إنشاء صورة مخصصة، فراجع مقال كتابة أول Dockerfile: تحويل سكربت Python إلى صورة (Image) معزولة.
في المثال التالي لدينا تطبيق ويب وخدمة قاعدة بيانات تعملان ضمن شبكة واحدة مع تخزين دائم:
services:
app:
build: .
container_name: myapp
ports:
- "3000:3000"
environment:
APP_ENV: production
DB_HOST: db
DB_PORT: 5432
DB_NAME: appdb
DB_USER: appuser
DB_PASSWORD: strongpassword
depends_on:
- db
restart: unless-stopped
db:
image: postgres:16
container_name: postgres_db
environment:
POSTGRES_DB: appdb
POSTGRES_USER: appuser
POSTGRES_PASSWORD: strongpassword
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
volumes:
postgres_data:
هذا الملف لا يصف فقط كيفية التشغيل، بل يصف العلاقات الداخلية أيضاً. الخدمة app تتصل بقاعدة البيانات عبر اسم الخدمة db وليس عبر IP متغير، وهذه ميزة تقلل هشاشة الإعدادات.
أوامر التشغيل الأساسية
بعد إنشاء الملف، يمكن إدارة المشروع بالأوامر التالية:
docker compose up -d
docker compose ps
docker compose logs -f
docker compose down
هذه الأوامر البسيطة تختصر وقتاً كبيراً في بيئات التطوير والاختبار. كما تجعل تعليمات التشغيل موحدة بين أعضاء الفريق، وهو عنصر مهم لتقليل الأخطاء البشرية.
أهم الفوائد العملية في بيئات DevOps
1) توحيد البيئة بين الفريق
حين يستخدم جميع المطورين الملف نفسه، تصبح بيئة التشغيل متناسقة. هذا يقلل الفروقات بين جهاز المطور وبيئة staging أو خادم الاختبار. وإذا كنت قد اطلعت على تثبيت Docker وإعداد بيئة العمل على Linux و Windows فستلاحظ أن Compose يكمل هذه البيئة بخطوة التشغيل الموحدة.
2) سهولة إدارة الخدمات المترابطة
في التطبيقات متعددة المكونات، وجود قاعدة بيانات، وذاكرة مؤقتة مثل Redis، وخادم عكسي، وخدمة تطبيق رئيسية أمر شائع. إدارة هذه العناصر ككيان واحد أسهل كثيراً من تشغيلها يدوياً واحدة تلو الأخرى.
3) دمج أفضل مع CI/CD
يمكن استخدام Docker Compose في اختبارات التكامل داخل GitHub Actions أو Jenkins لتشغيل خدمات التطبيق مؤقتاً أثناء الاختبار. هذا يضمن اختبار السلوك الحقيقي بين الخدمات بدلاً من الاكتفاء باختبارات معزولة ناقصة.
4) دعم التخزين الدائم والشبكات الداخلية
من أقوى مزايا Compose أنه يجعل تعريف volumes والشبكات الداخلية جزءاً من كود المشروع نفسه. ولمعرفة أهمية ذلك على قواعد البيانات تحديداً، راجع مقال التخزين الدائم (Docker Volumes): كيف نمنع ضياع قواعد البيانات عند توقف الحاوية؟.
متى يكون Docker Compose مناسباً؟ ومتى ننتقل إلى Kubernetes؟
Docker Compose ممتاز لبيئات التطوير المحلي، المشاريع الصغيرة والمتوسطة، الاختبارات، وبعض حالات النشر البسيطة على خادم واحد. لكنه ليس بديلاً كاملاً عن منصات التنسيق العنقودية مثل Kubernetes عندما تحتاج إلى التوسع الأفقي، التوزيع على عدة عقد، والتعافي التلقائي المتقدم.
بمعنى آخر، Compose مناسب عندما تكون المشكلة الأساسية هي تنظيم تشغيل عدة حاويات معاً. أما حين تصبح المشكلة هي إدارة بنية موزعة عالية التوفر، فستحتاج إلى منصة أوركسترا أكثر تقدماً.
لا تضع كلمات المرور أو مفاتيح
APIالحساسة مباشرة داخل ملفاتComposeفي المشاريع الحقيقية. استخدم ملفات.envبحذر، أو مديري أسرار مخصصين، وطبّق أقل صلاحية ممكنة لتقليل مخاطر الاختراق أو تسريب البيانات.
أخطاء شائعة يجب تجنبها
- الاعتقاد أن
depends_onيعني جاهزية الخدمة بالكامل، بينما هو غالباً يضمن ترتيب الإقلاع فقط. - عدم استخدام
healthcheckفي الخدمات الحرجة. - ربط مجلدات حساسة من النظام المضيف بدون مراجعة صلاحيات الوصول.
- تشغيل قواعد البيانات بدون تخزين دائم.
- استخدام ملفات ضخمة غير منظمة بدلاً من تقسيم البيئات إلى ملفات منفصلة عند الحاجة.
في أنظمة الإنتاج، راقب سياسات إعادة التشغيل مثل
unless-stoppedأوalwaysبعناية. الإعداد الخاطئ قد يسبب دوامة إعادة تشغيل مستمرة تؤدي إلى استهلاك الموارد وإخفاء أصل المشكلة بدلاً من حلها.
مثال واقعي: لماذا يحتاجه مشروع متعدد الخدمات؟
إذا كنت تبني منصة ويب فيها تطبيق Node.js، وقاعدة بيانات، وواجهة عكسية، فقد تضطر يدوياً إلى إنشاء شبكة، ثم تشغيل قاعدة البيانات، ثم تشغيل التطبيق مع متغيرات البيئة الصحيحة، ثم تشغيل Nginx مع الربط بين المنافذ. هذا يستهلك وقتاً ويزيد احتمال الخطأ.
أما مع Compose فيمكن التعبير عن هذا كله بملف واحد محفوظ داخل المستودع. وهذا النهج يتقاطع بوضوح مع ما تم شرحه في مقال مشروع مصغر: بناء وتغليف تطبيق تفاعلي مع قاعدة بيانات داخل حاوية معزولة حيث تصبح البنية قابلة للنقل والتكرار بسهولة.
الخلاصة
Docker Compose ليس مجرد أداة تشغيل مختصرة، بل هو طبقة تنظيمية مهمة تجعل المشاريع متعددة الحاويات قابلة للفهم، والتشغيل، والصيانة، والأتمتة. قيمته الحقيقية تظهر عندما تنتقل من تشغيل حاوية واحدة إلى إدارة منظومة خدمات مترابطة تحتاج إلى اتساق عالٍ بين التطوير والاختبار والنشر.
إذا كان Docker قد حل مشكلة عزل التطبيق، فإن Docker Compose يحل مشكلة تنسيق تشغيل مكونات المشروع ككيان واحد. ولهذا السبب يُعد أداة أساسية لأي مهندس DevOps أو مطور يتعامل مع بنى تطبيقات حديثة تتجاوز فكرة الحاوية الواحدة.
24 comments