أحمد حايس
الرئيسيةمن أناالدوراتالمدونةالعروض
أحمد حايس

دورات عربية متخصصة في التقنية والبرمجة والذكاء الاصطناعي.

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

تعلم أسرعوصول مباشر للدورات والمسارات من الموبايل.
تنقل أوضحالروابط الأساسية والدعم في مكان واحد بدون تشتيت.

المنصة

  • الرئيسية
  • من أنا
  • الدورات
  • العروض
  • المدونة

الدعم

  • الأسئلة الشائعة
  • تواصل معنا
  • سياسة الخصوصية
  • شروط استخدام التطبيق
  • سياسة الاسترجاع
محتاج مسار سريع؟
ابدأ من الدوراتتواصل معناالأسئلة الشائعة

© 2026 أحمد حايس. جميع الحقوق محفوظة.

الرئيسيةالدوراتالعروضالمدونةالدخول

أتمتة تنظيف Docker: كيف تحرر عشرات الجيجابايت بسكربت cron واحد

📅 ٢٠ أبريل ٢٠٢٦⏱ 5 دقائق قراءة
أتمتة تنظيف Docker: كيف تحرر عشرات الجيجابايت بسكربت cron واحد

أتمتة تنظيف Docker: كيف تحرر عشرات الجيجابايت بسكربت cron واحد

لو الـ VPS بتاعك امتلأ فجأة، الـ deploy وقف الساعة 2 الفجر، وبتلاقي 60% من المساحة مشغولة في /var/lib/docker — الحل مش docker system prune -a -f العمياء. هتخسر cache مهم وتعيد بناء صور هتحتاجها بكرة. السكربت اللي هنا بينظف بأمان ووفّر على سيرفر إنتاج واحد 44GB في أسبوع.

المشكلة باختصار

Docker بيترك ورا كل عملية build أو run خمس أنواع من المخلفات: طبقات صور قديمة (image layers)، حاويات متوقفة (stopped containers)، volumes يتيمة (dangling volumes)، build cache بيكبر بلا حدود، وlogs بتتراكم. على سيرفر CI/CD أو staging، ده بيوصل بسهولة لـ 40–70GB في الشهر. لما الـ disk يمتلئ، الـ Docker daemon بيقع والحاويات بتفشل تبدأ من جديد.

شاشة تيرمينال تعرض أوامر docker system prune ومخرجات تنظيف الصور والحاويات

تبسيط المفهوم أولًا: إيه هي الـ dangling images؟

تخيّل إنك بتعمل مسودّات لرسمة. كل مرة تعدّل حاجة، بتحتفظ بالنسخة القديمة على جنب "تحسّبًا". بعد 20 تعديل، عندك 20 نسخة، بس اللي فعلًا بتستخدمه هو الأخير. الـ dangling images هي بالظبط المسودّات دي: صور Docker قديمة من builds سابقة، مفيهاش tag دلوقتي، ومحدش بيستخدمها — بس لسه ماخدة مساحة.

علميًا: الـ dangling image هي أي image بـ tag <none>، يعني لا docker run ولا docker build بيشاور عليها. بتتولد لما تبني نفس الـ tag مرتين: البناء الأول بيبقى يتيم والتاني ياخد الـ tag. وعلى سيرفر CI بيبني كل commit، الأعداد بتتضاعف بسرعة.

ليه docker system prune -a خطر

docker system prune -a --volumes بيمسح كل image مش مستخدم حاليًا، حتى لو هتحتاجها خلال ساعة. على سيرفر CI بيبني نفس base images يوميًا (Node, Python, Postgres)، ده معناه إعادة تنزيل وإعادة بناء كل مرة. بناء كان بياخد 45 ثانية يبقى 3 دقائق.

بدل ما نعمل تنظيف مدمّر، الـ trade-off الذكي هو: احذف اللي أقدم من أسبوع، احتفظ بالـ cache الحديث. بتوفر 80% من المساحة، وبتخسر أقل من 15% من سرعة البناء.

السكربت الآمن — تنظيف مدروس بالـ filters

Bash
#!/usr/bin/env bash
set -euo pipefail

LOG="/var/log/docker-cleanup.log"
THRESHOLD_GB=10

echo "=== Docker cleanup $(date -Iseconds) ===" >> "$LOG"

# 1. احذف حاويات متوقفة أقدم من 24 ساعة
docker container prune -f --filter "until=24h" >> "$LOG" 2>&1

# 2. احذف الصور الـ dangling (بدون tag)
docker image prune -f >> "$LOG" 2>&1

# 3. احذف الصور غير المستخدمة الأقدم من 7 أيام
docker image prune -a -f --filter "until=168h" >> "$LOG" 2>&1

# 4. احذف volumes يتيمة
docker volume prune -f >> "$LOG" 2>&1

# 5. نظف build cache أقدم من 3 أيام، احتفظ بـ 5GB
docker builder prune -f --filter "until=72h" --keep-storage 5GB >> "$LOG" 2>&1

# 6. تنبيه لو المساحة لسه ضعيفة
FREE_GB=$(df -BG /var/lib/docker | awk 'NR==2 {gsub("G",""); print $4}')
if [ "$FREE_GB" -lt "$THRESHOLD_GB" ]; then
  echo "WARN: only ${FREE_GB}GB free after cleanup" | tee -a "$LOG"
fi

echo "free: ${FREE_GB}GB" >> "$LOG"

ركز على ثلاث نقاط جوهرية

  • --filter "until=168h": بيحفظ الصور المستخدمة آخر 7 أيام. ده بيحافظ على base images اللي الـ CI بيعتمد عليها.
  • --keep-storage 5GB: BuildKit بيحتفظ بـ 5GB cache كحد أقصى. أي زيادة بتتشال حسب الأقدم أولًا.
  • set -euo pipefail: لو أي خطوة فشلت السكربت بيقف فورًا. بدل ما يكمّل على حالة غلط ويكتب logs مربكة.

جدولة السكربت مع cron

Bash
sudo mv docker-cleanup.sh /usr/local/bin/
sudo chmod +x /usr/local/bin/docker-cleanup.sh
sudo crontab -e

# شغّل يومي 3 الفجر
0 3 * * * /usr/local/bin/docker-cleanup.sh

تأكد إن الـ user اللي بينفذ cron عنده صلاحيات docker. لو مش root: sudo usermod -aG docker $USER وسجّل خروج ودخول تاني.

الأرقام الفعلية من سيرفر إنتاج

رفوف سيرفرات في مركز بيانات مع أضواء LED تعبّر عن استهلاك مساحة القرص على الـ VPS

الأرقام دي من Hetzner CX32 (4 vCPU / 8GB RAM / 80GB disk) يشغّل 8 حاويات + GitHub Actions self-hosted runner:

  • قبل التشغيل: /var/lib/docker = 68GB (الـ disk فيه 4GB بس فاضيين).
  • بعد أول run: 31GB — وفّر 37GB في 40 ثانية.
  • بعد أسبوع من التشغيل اليومي: استقر حوالين 24GB.
  • المساحة المحررة شهريًا: ~44GB بشكل مستدام.
  • تأثير على زمن الـ build: متوسط build زاد من 45 ثانية لـ 52 ثانية (+15%). Acceptable.

الافتراض: الأرقام دي مبنية على سيرفر بـ ≤ 15 صورة فعّالة و ≤ 50 build يوميًا. لو عندك نمط استخدام مختلف، راجع الـ log أول أسبوع قبل ما تعتمد على السكربت.

متى لا تستخدم هذه الطريقة

لو السيرفر بيشغّل production containers بـ volumes مهمة مفيش ليها backup مستقل، شيل الخطوة رقم 4 (docker volume prune) أو بدّلها بمراجعة يدوية أسبوعية. الـ volumes اللي بتعتبرها Docker "يتيمة" ممكن تكون مرتبطة بحاوية بتتعمل restart متكرر أو stopped مؤقتًا، ومحوها معناه فقدان بيانات.

كمان، لو بتشغّل سيرفر development شخصي بتجرّب عليه كل يوم صور مختلفة، until=168h ممكن يكون طويل. قلّلها لـ 48h.

الخطوة التالية

انسخ السكربت، نفّذه يدويًا مرة بدون cron، وشوف كام GB اتحرّر من df -h /var/lib/docker. لو الرقم منطقي، ضيفه لـ crontab. بعد أسبوع، افتح /var/log/docker-cleanup.log وشوف الاتجاه. لو المساحة لسه بتقلّ، المشكلة في logs الحاويات نفسها — ضيف log-opts في /etc/docker/daemon.json بـ max-size: "50m" وmax-file: "3"، وده موضوع مقال تاني.

المصادر

  • Docker Docs — Prune unused Docker objects: docs.docker.com/engine/manage-resources/pruning
  • Docker Docs — BuildKit cache management: docs.docker.com/build/cache
  • Docker Docs — Configure logging drivers: docs.docker.com/engine/logging/configure
  • Linux man-pages — cron(8) و crontab(5): man7.org/linux/man-pages/man8/cron.8.html

هل استفدت من المقال؟

اطّلع على المزيد من المقالات والدروس المجانية من نفس المسار المعرفي.

تصفّح المدونة