Docker Compose
Docker Compose
التطبيق في بيئة الإنتاج نادرًا ما يكون حاوية واحدة. الخدمة الويب الاعتيادية تحتاج على أقل تقدير إلى ثلاثة مكونات: واجهة برمجية خلفية، وقاعدة بيانات علائقية، وذاكرة تخزين مؤقتة — إضافةً إلى معالج مهام خلفي ووسيط رسائل وخادم وكيل عكسي في حالات أكثر تعقيدًا. تشغيل كل هذه المكونات يدويًا عبر docker run يعني الربط اليدوي للشبكات والأحجام ومتغيرات البيئة وترتيب التشغيل. Docker Compose يحل هذه المعضلة بالسماح لك بتعريف المنظومة بأكملها في ملف YAML واحد والتحكم فيها بأمر واحد.
ما الذي تفعله Compose فعليًا
تقرأ Compose ملف docker-compose.yml (أو compose.yaml — كلاهما مقبول) وتترجمه إلى سلسلة منسّقة من استدعاءات Docker API: تنشئ شبكة bridge مخصصة، وتسحب الصور أو تبنيها، وتشغّل الحاويات بترتيب التبعية، وتركّب الأحجام، وتمرر متغيرات البيئة. والأهم أنها تمنح كل خدمة اسم DNS يطابق مفتاح الخدمة في الملف، فحاوية الواجهة البرمجية تصل إلى قاعدة البيانات باستخدام الاسم db فحسب — دون الحاجة إلى إدارة عناوين IP أو بنية اكتشاف الخدمات.
docker-compose (V1) وصل إلى نهاية دعمه الرسمي. يأتي Docker Desktop وDocker Engine الحديثان مع docker compose (بمسافة، لا شرطة) كإضافة CLI. استخدم docker compose في كل العمل الجديد؛ صيغة V1 متوافقة إلى حد بعيد لكن الإضافة أسرع ومدعومة.
تشريح ملف Compose
الملف التالي يعرّف منظومة ويب ثلاثية الطبقات: واجهة Node.js برمجية، وقاعدة بيانات PostgreSQL، وذاكرة تخزين مؤقتة Redis. اقرأ كل قسم بعناية — كل حقل يقابل خيار docker run تعرفته مسبقًا.
الاختيارات التصميمية الرئيسية في هذا الملف:
depends_onمعcondition: service_healthy— بدون هذا الخيار تبدأ الواجهة البرمجية فور انطلاق الحاوية وليس بعد أن تصبح PostgreSQL جاهزة فعلًا لقبول الاتصالات. هذا التنافس على التوقيت يُسبب فشل التشغيل في pipelines الـCI كل يوم.- الأحجام المسماة (
pg_data،redis_data) بدلًا من الربط المباشر لبيانات قاعدة البيانات — تبقى بعدdocker compose downوتُحذف فقط بـdocker compose down -v. لا تخزن بيانات قاعدة البيانات في bind mount أبدًا؛ يخلق ذلك تعارضات في أذونات الملفات بين مستخدم الجهاز المضيف والحاوية. - شبكة صريحة — عزل الخدمات على شبكة مسماة يمنعها من الوصول عشوائيًا إلى حاويات مشاريع Compose أخرى، وهو حاجز أمني حقيقي في البيئات المشتركة.
الأوامر الأساسية
معظم العمل اليومي مع Compose يستخدم حفنة من الأوامر:
docker compose down -v يحذف جميع الأحجام المسماة نهائيًا. تشغيل هذا الأمر على منظومة تحتوي قاعدة بيانات حقيقية يمحو البيانات بلا رجعة. تأكد دومًا من البيئة التي تعمل فيها قبل إضافة -v. في CI هذا مقبول؛ في بيئة التجهيز يكون كارثيًا.
ملفات البيئة واستبدال المتغيرات
ترميز الأسرار مباشرةً في compose.yaml ممارسة سيئة حتى للتطوير المحلي. تحمّل Compose تلقائيًا ملف .env من مجلد المشروع، ويمكنك الإشارة إلى متغيراته بصيغة ${VAR}:
لبيئات متعددة يمكنك الاحتفاظ بملفات تجاوز منفصلة ودمجها عند التشغيل:
compose.yaml— التعريفات الأساسية، مُضافة إلى gitcompose.override.yaml— تُدمج تلقائيًا عند وجودها؛ مثالية للإضافات المحلية مثل bind-mount للكود المصدري ومنافذ التصحيحcompose.ci.yaml— تُدمج صراحةً في CI بـdocker compose -f compose.yaml -f compose.ci.yaml up -d
الملفات الشخصية Profiles: خدمات شرطية
تتيح الملفات الشخصية تعريف خدمات لا تُشغَّل افتراضيًا وتُفعَّل عند الطلب فقط. هذا الحل النظيف لمشكلة "أريد منظومة المراقبة في CI فقط" أو "شغّل بذر البيانات مرةً واحدة":
debug — تعمل عند الطلب وغير مرئية في غير ذلك. هذا النمط يقضي على فئة "تركتُ Adminer مكشوفًا" من حوادث الأمان.
منظومات التطوير المحلي: ربط مباشر لإعادة التحميل الفوري
في التطوير النشط تريد دائمًا تقريبًا تركيب كودك المصدري داخل الحاوية حتى ترى التغييرات فورًا دون إعادة البناء. استخدم compose.override.yaml لذلك كي لا يصل الربط المباشر إلى CI أو الإنتاج:
الحجم المجهول /app/node_modules نمط معروف: يمنع node_modules الجهاز المضيف (المبني لنظام macOS/Windows) من الطغيان على نظير الحاوية (المبني لـLinux)، وهو ما يسبب فشل الثنائيات الأصلية. نفس النمط ينطبق على __pycache__ في Python وbundle في Ruby وذاكرة الوحدات في Go.
اعتبارات بيئة الإنتاج
Compose ممتازة للتطوير المحلي والنشر الصغير النطاق (خادم واحد يُشغّل منظومة متكاملة). على نطاق الإنتاج الأوسع تتدرج الفرق إلى Kubernetes. لكن Docker Compose لا تزال مستخدمة في الإنتاج في شركات كثيرة من أجل:
- النشر على خادم واحد عبر
docker compose up -dمُدار بـpipeline CI - بيئات اختبار التكامل في CI — تشغيل قاعدة بيانات وذاكرة تخزين مؤقتة حقيقيتين بدل محاكاتهما
- منظومات الأدوات الداخلية التي لا تستحق تعقيد Kubernetes
عند تشغيل Compose في CI، ثبّت دائمًا وسوم الصور بـdigests أو إصدارات محددة (لا تستخدم latest أبدًا) لتضمن قابلية الاستنساخ. استخدم --wait (docker compose up -d --wait) في CI — يُوقف التنفيذ حتى تُبلّغ جميع الخدمات ذات الفحوصات الصحية بالجاهزية قبل المرحلة التالية من الـpipeline.