لماذا قائمة تحقق قبل الإنتاج
صُمِّم Docker Compose للتطوير: قيمه الافتراضية تفضِّل البساطة على المتانة. في التطوير لا تشكِّل هذه الإعدادات أي مشكلة. في الإنتاج تتحول إلى حوادث: قرص ممتلئ الساعة الثالثة فجرًا، قاعدة بيانات ضائعة بعد docker compose down، خدمة غير متاحة بعد انقطاع الكهرباء. البشرى: تقوية حزمة Compose لا تتطلب إعادة كتابة، بل عشر إضافات مستهدفة فحسب. مرر كل نقطة في هذه القائمة قبل الإطلاق وستصمد خدمتك أمام الأحمال وعمليات إعادة التشغيل بلا مراقبة مستمرة.
النقاط العشر بلمحة
- restart: unless-stopped — تُعاد الحاوية بعد إقلاع المضيف أو انهيارها
- healthcheck — يكتشف Docker حاوية عالقة ويتيح إعادة التشغيل التدريجي
- حدود المعالج والذاكرة — خدمة جامحة لا يمكنها خنق جيرانها
- الأسرار عبر .env أو Docker secrets — لا كلمة مرور بنص صريح
- وحدات تخزين مُسمَّاة — تنجو البيانات من
docker compose down - تدوير السجلات —
max-sizeوmax-fileيمنعان امتلاء القرص - عزل الشبكة — افصل
frontendوbackend - ربط المنافذ —
127.0.0.1:PORTخلف وكيل عكسي، لا0.0.0.0 - وسوم صور مثبَّتة — نسخة أو بصمة، لا
latest - depends_on مع شرط —
service_healthyيتجنب سباقات الإقلاع
المتطلبات المسبقة
تأكد من امتلاك خادم VPS مثبَّت عليه Docker Engine وإضافة Compose v2. تحقَّق من الإصدار عبر docker compose version. ضع ملفك في مجلد مشروع مخصص مع ملف .env بجانبه وأذونات مقيَّدة (chmod 600 .env). خطِّط لوكيل عكسي في المقدمة. احتفظ بنسخة من ملف Compose تحت إدارة إصدارات.
الخطوات العشر المفصَّلة
1. سياسة إعادة التشغيل
أضف
restart: unless-stoppedإلى كل خدمة. تُعاد الحاوية بعد انهيار أو إقلاع المضيف، لكنها تبقى موقوفة إذا أوقفتها بإرادتك. تجنَّبrestart: alwaysالذي يُعيد تشغيل حتى حاوية أردتَ إيقافها، وفضِّلunless-stoppedللخدمات التطبيقية وon-failureللمهام الوقتية.2. الفحص الصحي
أعلن كتلة
healthcheck:معtestوinterval(مثلاً30s) وtimeout(مثلاً10s) وretries(مثلاً3). أضفstart_period: 40sللخدمات البطيئة في الإقلاع حتى لا تُعدَّunhealthyأثناء التهيئة. يُعلِّم Docker الحاوية بـhealthyأوunhealthyمما يتيح لـdepends_on: condition: service_healthyانتظار الجاهزية الفعلية.3. حدود الموارد
تحت
deploy.resources.limits، حدِّدcpusوmemory(مثلاًmemory: 512M). بلا حد تستطيع خدمة نازفة استهلاك كل الذاكرة وتُفعِّل قاتل OOM. أضفreservationsلضمان حد أدنى عند الإقلاع.4. الأسرار خارج الملف
لا تضع أبدًا كلمة مرور بنص صريح في YAML. أرجع إليها عبر
env_fileأوsecrets:الذي يُحمِّل الأسرار كملفات تحت/run/secrets/داخل الحاوية، بعيدًا عنdocker inspect. أضف.envإلى.gitignore.5. وحدات التخزين المُسمَّاة
أعلن بياناتك في وحدات تخزين مُسمَّاة بمشغِّل صريح. وحدة التخزين المسمَّاة تنجو من
docker compose down؛ يمحوها فقطdown -v. وثِّق كل وحدة تخزين واربطها باستراتيجية استرداد مختبَرة.6. تدوير السجلات
أضف
logging:معdriver: json-fileوخياريَّيmax-sizeوmax-file. بلا هذا تملأ سجلات حاوية ثرثارة القرص حتى العطل. طبِّقه على كل خدمة.7. عزل الشبكة
أنشئ شبكات مُسمَّاة
frontendوbackendوأرفق كل خدمة فقط بما تحتاجه. أضفinternal: trueعلى شبكةbackendلمنع أي وصول من المضيف أو الإنترنت.8. ربط المنافذ
انشر على
127.0.0.1:8080:8080لا8080:8080خلف وكيل عكسي. Docker يعدِّل قواعد iptables مباشرة وقد يتجاوز UFW — ربط127.0.0.1هو الضمان الوحيد الموثوق.9. وسوم الصور المثبَّتة
استبدل
latestبنسخة محددة أو بصمة. استخدمpull_policy: missingلسلوك متوقع: لا يسحب Compose صورة جديدة إلا إذا كانت غائبة محليًا.10. ترتيب الإقلاع
استخدم
depends_onمعcondition: service_healthy. للخدمات التي لا تدعم فحصًا صحيًا أصليًا، استخدمcondition: service_startedمع سكريبت انتظار مثلwait-for-it.sh.
إعدادات التطوير مقابل الإنتاج
مرّر الجدول أفقيًا
| الإعداد | افتراضي التطوير | موصى به للإنتاج |
|---|---|---|
| restart | no | unless-stopped |
| healthcheck | غائب | مُعرَّف بفترة ومحاولات |
| الذاكرة | بلا حد | حد محدد |
| الأسرار | نص صريح ممكن | .env أو Docker secrets |
| وحدات التخزين | مجهولة | مُسمَّاة |
| السجلات | بلا حد | max-size + max-file |
| الشبكة | الجسر الافتراضي | frontend / backend |
| المنافذ | 0.0.0.0 | 127.0.0.1 خلف وكيل |
| الصورة | latest | نسخة أو بصمة |
| depends_on | الإطلاق فقط | condition: service_healthy |
الفحوصات الصحية المتقدمة: مراقبة الحالة الفعلية للخدمة
فحص صحي جيد التهيئة يتجاوز curl البسيط: يقيس الحالة الوظيفية للخدمة لا مجرد التوافر الشبكي. لواجهة برمجية HTTP اختبر نقطة نهاية خفيفة (/health أو /ready) تُعيد 200 فقط إذا كان اتصال قاعدة البيانات قائمًا. لـPostgreSQL استخدم pg_isready -U postgres. لـRedis يكفي redis-cli ping. تحقق من حالة حاوياتك بـdocker compose ps: العمود STATUS يعرض healthy أو unhealthy أو starting. حاوية عالقة في starting لأطول من start_period تشير إلى مشكلة تهيئة — راجع docker compose logs service لمعرفة السبب. المعامل start_period مستقل عن interval: يحدد نافذة سماح لا تُحسب فيها الإخفاقات ضمن retries، وهو ضروري للخدمات التي تحتاج وقتًا للترحيل أو التعبئة.
Docker secrets بدون Swarm: تحميل الملفات في /run/secrets/
منذ Compose v2.24، يعمل آلية secrets: في وضع مستقل بدون Swarm. أعلن سرًا في قسم secrets: بمستوى الجذر مشيرًا إلى ملف محلي (file: ./secrets/db_password.txt)، ثم أشر إليه في كل خدمة بـsecrets: [db_password]. يُحمِّل Docker هذا الملف قراءة فقط في /run/secrets/db_password داخل الحاوية. التطبيق يقرأ السر كملف عادي، ولا يظهر هذا المحتوى أبدًا في docker inspect ولا في متغيرات البيئة ولا في السجلات. للتدوير بدون توقف: أنشئ db_password_v2 بجانب db_password_v1، حدِّث الخدمة، أعد النشر بـdocker compose up -d --no-deps service، احذف v1 بعد التحقق.
التراجع: العودة إلى الوراء بعد نشر فاشل
التراجع عن حزمة Compose يُجهَّز قبل النشر لا بعد الحادثة. الاستراتيجية الدنيا هي الإبقاء على الصورة السابقة مُوسَمةً ومتاحة. للتراجع: عدِّل الوسم في ملف Compose أو في ملف .env إن كانت النسخة متغيرًا، ثم أعد تشغيل docker compose up -d. وحدات بيانات التخزين لا تتأثر بتغيير الصورة مما يجعل التراجع التطبيقي سريعًا. إذا احتاجت النسخة السابقة ترحيل مخطط عكسي، جهِّزه قبل نشر النسخة الجديدة. للنشرات الحرجة، اعتمد نظام ملفَّين: docker-compose.yml (نسخة مستقرة) وdocker-compose.override.yml (نسخة مرشَّحة) — الأمر docker compose -f docker-compose.yml up -d يعود فورًا للحالة المستقرة.
اختبر دائمًا حزمتك المقوَّاة محليًا: docker compose config للتحقق من البنية، ثم محاكاة الإقلاع بـdocker compose restart. تأكد أن الحاويات تعود healthy وأن البيانات تستمر بعد down يعقبه up.
استكشاف الأخطاء: 5 أخطاء شائعة وحلولها
network not found: بعد docker compose down تُحذف الشبكات المسمَّاة. الحل: أعلن الشبكات المشتركة بـexternal: true أو زامن إعادة تشغيل الحزم التابعة. port is already in use: عملية أخرى تشغل المنفذ. حدِّدها بـss -tlnp | grep :PORT ثم أوقفها. OOM: النواة تقتل حاوية بلا إنذار — ابحث عن OOMKilled: true في docker inspect container_id. ارفع حد الذاكرة أو حدِّد التسريب بـdocker stats. permission denied on volume: العملية تعمل بـUID لا يملك صلاحية الوصول. تحقق من UID بـdocker compose exec service id ثم عدِّل الأذونات. حاوية تُعاد في حلقة: docker compose logs --tail=50 service يكشف خطأ الإقلاع. الأسباب الشائعة: متغير بيئة مفقود، ملف إعداد غير موجود، أو تبعية غير جاهزة.
CVE-2026-17106 (CopyEscape): تحديث Docker Engine فورًا
CVE-2026-17106، الملقَّب بـCopyEscape، هو حالة تسابق زمني في docker cp أُفصح عنها في 10 أغسطس 2026. حاوية غير موثوقة تنتج أرشيف tar مشوَّهًا يتبع رابطًا رمزيًا خارج الوجهة، مما يؤدي إلى كتابة ملف عشوائي على المضيف. التصحيح في Docker Engine ≥ 29.7.2 وDocker Desktop ≥ 4.86.0.
نسخ الأحجام احتياطيًا دون تلف
نسخ ملفات حجم PostgreSQL أو MySQL أثناء تشغيلها بـrsync أو tar ينتج نسخة تالفة. القاعدة: دائمًا pg_dump أو mysqldump قبل لقطة الحجم. أدوات مثل Restic وOffen Docker Backup تُنظِّم هذا تلقائيًا.
الخاتمة
تحوِّل هذه الإعدادات العشرة ملف Compose تطويريًا إلى حزمة إنتاجية. أقسام الفحوصات الصحية المتقدمة والأسرار المُحمَّلة كملفات والتراجع واستكشاف الأخطاء تكمل هذا الأساس وتمنحك ردود الفعل للتدخل السريع. لا يتطلَّب أي من هذه النقاط أداةً إضافية: كل شيء في YAML لديك بالفعل.