المستوى: متوسط — الشرح مبني على فرضية إنك بتشغّل Docker على خادم Linux واحد وبتعرف أساسيات الأوامر.
سكربت واحد في cron بيستعيد لك عشرات الجيجابايت من قرص الخادم كل أسبوع، من غير ما تلمس بياناتك ولا توقّف أي خدمة شغّالة.
أتمتة تنظيف Docker: استعِد مساحة قرص خادمك بأمان
المشكلة باختصار
الـ Docker مبيحذفش حاجة لوحده. كل build بيسيب صور معلّقة، وكل حاوية بتقف بتفضل على القرص، وكاش البناء بيكبر كل يوم. النتيجة: خادم بيوصل 90% امتلاء والتطبيق بيقف، والسيرفر "مرتاح". لو عندك خادم CI بيبني الصور 30 مرة في اليوم، ده ممكن ياكل 5 إلى 8 جيجا يوميًا.
ليه القرص بيمتلي أصلًا
خلّيها بمثال بسيط الأول. الصور القديمة والحاويات الميتة زي الكراتين الفاضية اللي بتتكدس في المخزن بعد كل شحنة. كرتونة أو اتنين مش مشكلة، لكن بعد شهر المخزن مليان كراتين مالهاش لازمة وانت مش لاقي مكان للبضاعة الجديدة. عامل النظافة اللي بيرمي الكراتين القديمة بس، وميلمسش البضاعة اللي لسه بتتباع، هو بالظبط اللي محتاجينه.
علميًا: كل docker build بينتج طبقات وسيطة وصور بدون tag اسمها dangling images. كل حاوية وقفت بتفضل محجوزة على القرص. وكاش البناء (build cache) بيتراكم مع كل بناء. Docker بيعتبرها "غير مستخدمة" لكنه مبيحذفهاش من نفسه عشان ميضيّعش حاجة انت ممكن تحتاجها.
الحل: تنظيف مجدوَل وآمن
الفكرة إنك تشغّل docker system prune بشكل تلقائي، بس بحرص. أهم قاعدة: متحذفش أي حاجة عمرها أقل من أسبوع، عشان متكسرش rollback أو build لسه محتاجه.
#!/usr/bin/env bash
set -euo pipefail
LOG=/var/log/docker-cleanup.log
echo "=== $(date '+%F %T') بدء التنظيف ===" >> "$LOG"
before=$(df --output=used -BG / | tail -1 | tr -dc '0-9')
# احذف الصور والحاويات والشبكات غير المستخدمة الأقدم من 7 أيام فقط
docker system prune --all --force --filter "until=168h" >> "$LOG" 2>&1
# نظّف كاش البناء الأقدم من أسبوع
docker builder prune --force --filter "until=168h" >> "$LOG" 2>&1
after=$(df --output=used -BG / | tail -1 | tr -dc '0-9')
echo "المساحة المستخدمة: قبل ${before}G / بعد ${after}G" >> "$LOG"
وبعدين ضيفه في crontab يشتغل كل ليلة الساعة 2 صباحًا:
0 2 * * * /usr/local/bin/docker-cleanup.shليه الأوامر دي بالظبط
--all: يحذف كل الصور غير المستخدمة، مش المعلّقة (dangling) بس.--filter "until=168h": يحمي أي حاجة اتعملت خلال آخر 7 أيام. ده صمام الأمان اللي بيمنعك تمسح صورة لسه شغّالة أو محتاجها.- من غير
--volumesبقصد: الـ volumes بتاعت قواعد بياناتك متتلمسش. Docker أصلًا مبيحذفش الـ volumes افتراضيًا لنفس السبب: خوفًا على بياناتك.
القياس: قبل وبعد
على خادم بناء حقيقي بيعمل حوالي 20 deploy في اليوم، القرص كان وصل 88% (88 جيجا من 100). بعد أول تشغيل للسكربت نزل لـ 39% — يعني استعاد حوالي 49 جيجا. الأرقام دي تقديرية وبتختلف حسب حجم صورك وعدد الـ builds، بس النمط ثابت: أول تنظيف بيرجّع أكبر مساحة، وبعدها بيثبت على تنظيف يومي بسيط بيمنع القرص إنه يمتلي تاني.
الـ trade-offs اللي لازم تعرفها
تنظيف كاش البناء بيوفّر مساحة، بس بتخسر سرعة أول build بعد التنظيف. لو مسحت الكاش كله، البناء اللي بعده ممكن ياخد 3 إلى 4 أضعاف الوقت لأنه هيعيد كل طبقة من الصفر. عشان كده بنستخدم until=168h: بتكسب مساحة، وبتحتفظ بكاش آخر أسبوع فيفضل البناء سريع. الافتراض هنا إنك بتبني بشكل متكرر؛ لو بتبني مرة في الأسبوع، زوّد المدة لـ 720h مثلًا.
متى لا تستخدم هذه الطريقة
متشغّلش السكربت ده على nodes بتاعة Kubernetes — الـ kubelet عنده garbage collection للصور بيتكفّل بالموضوع تلقائيًا، وتدخّلك اليدوي ممكن يمسح صورة Pod محتاجها. وكمان لو بتعتمد على صور قديمة بـ tag ثابت للـ rollback الفوري، خلّي بالك إن --all ممكن يشيلها طالما مش مستخدمة دلوقتي؛ في الحالة دي احمِ الصور دي واستثنِها بـ label. وعلى لابتوب فيه مساحة كتير، التنظيف المجدوَل رفاهية مش محتاجها — نضّف يدويًا لما تحتاج.
المصادر
- docker system prune — التوثيق الرسمي: السلوك الافتراضي، وإن الـ volumes لا تُحذف افتراضيًا، وفلتر
untilاللي بيقبل مدد زي168h. - Prune unused Docker objects — Docker Docs: شرح الصور المعلّقة والحاويات المتوقفة وكاش البناء.
- docker system df — Docker Docs: قياس المساحة القابلة للاستعادة (RECLAIMABLE).
- Kubernetes Garbage Collection: ليه مفيش داعي للتنظيف اليدوي على nodes الـ cluster.
الخطوة التالية
شغّل docker system df دلوقتي وبُص على عمود RECLAIMABLE. لو لقيت أكتر من 20% من قرصك قابل للاستعادة، حط السكربت في cron النهارده وسيبه يشتغل ليلة واحدة، وبُص على اللوج الصبح في /var/log/docker-cleanup.log وشوف كسبت كام جيجا.