SSD Nodes Learn 🎉 VPS از $5.50/ماه
راهنماها Matt Connorتوسط Matt Connor

پاک‌سازی فضای دیسک در Docker با دستور prune

اگر با خطای پر شدن دیسک در VPS مواجه هستید، با استفاده از دستورات docker system prune و بررسی دایرکتوری var/lib/docker فضای اشغال شده را بدون حذف داده‌های مهم آزاد کنید.

پیش از هرگونه پاک‌سازی، مشخص کنید چه چیزی فضای دیسک را اشغال کرده است

Docker در یک VPS فضا را در چهار بخش اشغال می‌کند: imageها، containerهای متوقف‌شده، build cache و volumeهای محلی. ابتدا docker system df را اجرا کنید تا بفهمید کدام بخش فضا را اشغال کرده است، سپس دقیق‌ترین دستور prune را برای پاک‌سازی آن اجرا کنید. ترتیب اهمیت دارد، زیرا آخرین دستور در این راهنما، یعنی docker volume prune -a، داده‌ها را حذف می‌کند و امکان بازگردانی وجود ندارد.

با فایل‌سیستم شروع کنید، نه با Docker.

df -h /
sudo du -xh --max-depth=1 /var/lib/docker | sort -h

df به شما می‌گوید وضعیت چقدر بحرانی است. du نشان می‌دهد فضا کجا رفته است. فلگ -x باعث می‌شود du فقط روی یک فایل‌سیستم باقی بماند تا از mountها به volumeهای دیگر عبور نکند و فضا را دو بار محاسبه نکند. پنج دایرکتوری در اینجا اهمیت دارند: overlay2 که لایه‌های image و container را نگه می‌دارد، volumes که داده‌های volume را در خود دارد، containers که متادیتای container و فایل‌های لاگ را نگه می‌دارد، buildkit که build cache را در بر می‌گیرد و image که متادیتای لایه‌ها را ذخیره می‌کند.

نکته‌ای درباره sudo و wildcardهای شل، چرا که وقت زیادی از کاربران می‌گیرد. مالک /var/lib/docker کاربر root است و توسط کاربر معمولی شما قابل خواندن نیست، بنابراین ls /var/lib/docker خطای Permission denied را برمی‌گرداند. دستوری مانند sudo du -sh /var/lib/docker/* نیز شکست می‌خورد، زیرا شل شما پیش از اجرای sudo، عبارت * را بسط می‌دهد و شل شما اجازه خواندن آن دایرکتوری را ندارد. هر دستوری که در ادامه می‌آید، دقیقاً به همین دلیل از find یا --max-depth به جای wildcard استفاده می‌کند.

حالا دیدگاه خود Docker را بررسی کنید.

docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          24        6         12.4GB    8.91GB (71%)
Containers      31        6         1.42GB    1.39GB (97%)
Local Volumes   14        5         6.03GB    4.11GB (68%)
Build Cache     212       0         9.87GB    9.87GB

این ارقام مربوط به یک ماشین خاص هستند و وضعیت ماشین شما را نشان نمی‌دهند. به ساختار خروجی دقت کنید. TOTAL تعداد آبجکت‌ها، ACTIVE تعداد آبجکت‌های در حال استفاده و RECLAIMABLE برآورد Docker از فضایی است که با دستور prune در آن ردیف آزاد می‌شود.

دو نکته درباره RECLAIMABLE وجود دارد که کاربران را به اشتباه می‌اندازد. این دستور لایه‌های مشترک image را برای هر image که از آن‌ها استفاده می‌کند می‌شمارد، بنابراین ردیف image معمولاً فضایی بیش از آنچه واقعاً آزاد می‌شود را نشان می‌دهد. همچنین این دستور هرگز فایل‌های لاگ container را شامل نمی‌شود، زیرا Docker فایل لاگ را به عنوان یک آبجکت قابل بازیافت در نظر نمی‌گیرد. وقتی du دایرکتوری‌ای را بسیار بزرگ‌تر از آنچه docker system df گزارش می‌دهد نشان می‌دهد، دلیل آن فایل‌های لاگ هستند و بخشی در ادامه به این موضوع اختصاص دارد.

برای مشاهده جزئیات هر آبجکت، -v را اضافه کنید.

docker system df -v

این کار خلاصه را به بخش‌های مجزا برای هر نوع آبجکت تقسیم می‌کند. بخش image ستون‌های SHARED SIZE و UNIQUE SIZE را اضافه می‌کند تا بتوانید هزینه واقعی یک image خاص را ببینید. بخش volume یک شمارنده LINKS اضافه می‌کند که تعداد containerهای متصل به آن volume است. LINKS را به خاطر بسپارید، زیرا مقدار 0 تنها معیاری است که دستورات prune برای volumeها بر اساس آن عمل می‌کنند.

تصاویر معلق (Dangling) در مقابل تصاویر استفاده‌نشده (Unused)

این دو عبارت ممکن است مترادف به نظر برسند، اما چنین نیستند. فیلترها به دلیل تفاوت ماهوی اشیاء، رفتار متفاوتی دارند.

یک تصویر معلق، تصویری است که هیچ برچسبی (tag) ندارد. این تصاویر در خروجی <none> به صورت docker images نمایش داده می‌شوند. شما با هر بار بازسازی (rebuild) یکی از آن‌ها را ایجاد می‌کنید: docker build -t myapp:latest . برچسب myapp:latest را به تصویر جدید منتقل می‌کند و تصویر قدیمی تمام لایه‌های خود را حفظ می‌کند اما نامش را از دست می‌دهد. هیچ‌چیز به آن ارجاع نمی‌دهد و هیچ فرآیندی به‌طور خودکار آن را پاکسازی نمی‌کند.

یک تصویر استفاده‌نشده، هر تصویری است (چه برچسب‌دار و چه بدون برچسب) که در حال حاضر هیچ کانتینری به آن ارجاع نمی‌دهد. تصویری که postgres:16 ماه گذشته دریافت (pull) کرده‌اید و در حال حاضر در حال اجرا نیست، استفاده‌نشده محسوب می‌شود و لزوماً معلق نیست.

docker image prune        # dangling images only
docker image prune -a     # every image no container refers to

دستور دوم ابتدا سوال می‌پرسد.

WARNING! This will remove all images without at least one container associated to them.
Are you sure you want to continue? [y/N]

آن اعلان (prompt) را با دقت بخوانید. عبارت "Associated to them" به یک شیء کانتینر موجود اشاره دارد، چه در حال اجرا باشد و چه متوقف شده باشد. اگر دستور docker compose down را اجرا کرده باشید، کانتینرها حذف شده‌اند؛ بنابراین هر تصویری که آن سرویس‌ها استفاده می‌کردند اکنون استفاده‌نشده است و -a همه آن‌ها را حذف می‌کند. هیچ چیزی که نتوانید دوباره به دست آورید از بین نمی‌رود، اما دستور docker compose up -d بعدی، تمام آن‌ها را دوباره دریافت یا بازسازی می‌کند که در یک VPS کوچک، هزینه پهنای باند و زمان ساخت را به همراه دارد. این یکی از دلایل عملی برای دانستن تفاوت حذف کانتینرها با docker compose down و وضعیت آن‌ها پس از stop پیش از اجرای هرگونه عملیات پاکسازی (prune) است.

یک فیلتر، تصاویر اخیر را از محدوده عملیاتی خارج می‌کند.

docker image prune -a --filter "until=240h"

این دستور تصاویر استفاده‌نشده‌ای را که بیش از 240 ساعت (10 روز) پیش ایجاد شده‌اند حذف می‌کند و تصاویر جدیدتر را دست‌نخورده باقی می‌گذارد. مقدار until یک رشته زمانی Go مانند 240h یا یک برچسب زمانی مطلق مانند 2026-08-01T00:00:00 را می‌پذیرد.

کش ساخت (build cache) چیست و چرا بدون محدودیت رشد می‌کند

BuildKit موتوری است که Docker به‌صورت پیش‌فرض از نسخه Docker Engine 23.0 برای docker build و docker compose build استفاده می‌کند. این ابزار نتیجه هر مرحله از هر Dockerfile که اجرا می‌شود را کش می‌کند و این کش را در مسیر /var/lib/docker/buildkit نگه می‌دارد. دلیل اینکه ساخت دوم شما در چند ثانیه تمام می‌شود همین کش است، بنابراین وظیفه خود را به‌درستی انجام می‌دهد. مشکل اینجاست که به‌صورت پیش‌فرض هیچ مکانیزمی برای منقضی کردن ورودی‌های قدیمی وجود ندارد. اگر یک ایمیج را پنجاه بار با یک مرحله COPY که هر بار تغییر می‌کند بسازید، پنجاه مجموعه از لایه‌ها را در حافظه نگه می‌دارید.

کش ساخت برای docker image prune نامرئی است. این یک نوع شیء مجزا با دستور اختصاصی خود است.

docker builder prune                        # dangling cache
docker builder prune -a                     # all unused cache
docker builder prune --filter until=168h    # cache untouched for 7 days

هیچ‌کدام از این دستورات به ایمیج‌ها یا داده‌های شما دست نمی‌زنند. تنها هزینه پاک‌سازی کش ساخت این است که ساخت بعدی یک‌بار به‌کندی انجام می‌شود. روی یک VPS که به‌طور منظم ایمیج‌ها را بازسازی می‌کند، Build Cache اغلب بزرگ‌ترین ردیف در docker system df است، که آن را به امن‌ترین مورد حجیم برای حذف تبدیل می‌کند.

دستورات prune، مرتب‌شده از ایمن تا مخرب

این فهرست را به ترتیب دنبال کنید و به محض اینکه df -h / دوباره سالم به نظر رسید، متوقف شوید. هر دستور پس از پایان کار، یک خط Total reclaimed space: چاپ می‌کند.

  1. docker container prune کانتینرهای متوقف‌شده را حذف می‌کند. لایه‌های قابل‌نوشتن آن‌ها نیز پاک می‌شوند، بنابراین هر چیزی که کانتینر خارج از یک volume نوشته باشد، همراه با آن حذف خواهد شد. به volumeها دست زده نمی‌شود.
  2. docker image prune فقط imageهای معلق (dangling) را حذف می‌کند. این ایمن‌ترین دستور برای imageها است.
  3. docker builder prune کش ساخت (build cache) معلق را حذف می‌کند. هزینه آن، یک بار build کندتر در آینده است.
  4. docker image prune -a تمام imageهایی که هیچ کانتینری به آن‌ها ارجاع نمی‌دهد را حذف می‌کند. هزینه آن، نیاز به pull یا build مجدد است.
  5. docker system prune سه مورد اول را هم‌زمان انجام داده و شبکه‌های استفاده‌نشده را نیز اضافه می‌کند.
  6. docker volume prune volumeهای ناشناس (anonymous) استفاده‌نشده را حذف می‌کند.
  7. docker volume prune -a volumeهای استفاده‌نشده، شامل volumeهای نام‌گذاری‌شده را حذف می‌کند. این دستوری است که پایگاه‌های داده را حذف می‌کند.

docker system prune پیش از اجرا، محدوده عملکرد خود را اعلام می‌کند.

WARNING! This will remove:
        - all stopped containers
        - all networks not used by at least one container
        - all dangling images
        - unused build cache
Are you sure you want to continue? [y/N]

volumeها عمداً از آن فهرست حذف شده‌اند. افزودن --volumes، volumeهای ناشناس را به محدوده عملیات بازمی‌گرداند. افزودن -a، مرحله imageها را از imageهای معلق به تمام imageهای استفاده‌نشده گسترش می‌دهد. اجرای یک docker system prune -a --volumes -f کامل روی یک میزبان عملیاتی (production)، روشی است که افراد در حین تلاش برای آزادسازی فضا، داده‌های خود را از دست می‌دهند.

چرا پاک‌سازی (pruning) ولوم‌ها باعث حذف دیتابیس شما می‌شود

این بخشی است که باید دو بار بخوانید.

یک ولوم زمانی «استفاده‌نشده» تلقی می‌شود که هیچ کانتینری به آن متصل نباشد. این تنها معیار بررسی است. Docker بررسی نمی‌کند که آیا ولوم خالی است، آیا فایل compose همچنان آن را تعریف کرده است، یا اینکه آیا تنها نسخه از دیتابیس شما در آن قرار دارد. LINKS 0 در docker system df -v به معنای قابل پاک‌سازی بودن است و هیچ معنای دیگری ندارد.

حالا دو اقدام معمولی را پشت سر هم در نظر بگیرید. شما docker compose down را اجرا می‌کنید تا یک stack را به‌طور تمیز راه‌اندازی مجدد کنید. این دستور کانتینرها را حذف می‌کند و ولوم‌های نام‌گذاری‌شده را سر جایشان باقی می‌گذارد؛ که دقیقاً همان کاری است که مستندات آن را تأیید می‌کنند. ولوم Postgres شما اکنون به هیچ‌چیز متصل نیست. ده دقیقه بعد، شما docker volume prune -a را برای آزادسازی فضا اجرا می‌کنید و دیتابیس از بین می‌رود. هر دو دستور به‌درستی عمل کرده‌اند. این توالی باعث نابودی داده‌ها شد.

از زمان Docker Engine 23.0 (نسخه API 1.42)، دستور ساده پاک‌سازی محدودتر از گذشته شده است.

WARNING! This will remove anonymous local volumes not used by at least one container.

ولوم ناشناس (anonymous volume) ولومی است که Docker برای شما ایجاد کرده است، معمولاً به این دلیل که یک image دستور VOLUME را اعلام کرده و شما هرگز نامی برای آن تعیین نکرده‌اید. این ولوم‌ها معمولاً داده‌هایی را نگه می‌دارند که شما درخواست نگهداری‌شان را نداده‌اید. یک ولوم نام‌گذاری‌شده (named volume)، همان نوعی که در فایل compose خود نوشته‌اید، تنها زمانی حذف می‌شود که شما -a را اضافه کنید. نسخه‌های قدیمی‌تر Docker هر دو نوع را با دستور ساده حذف می‌کردند، بنابراین به عادت‌هایی که در سیستمی که از آن زمان ارتقا یافته شکل گرفته‌اند، اعتماد نکنید. این تفاوت تنها زمانی معنا پیدا می‌کند که بدانید ولوم‌های نام‌گذاری‌شده چه تفاوتی با bind mountها دارند، زیرا یک bind mount اصلاً ولوم Docker محسوب نمی‌شود و هیچ دستور prune هرگز به آن دسترسی نخواهد داشت.

پیش از حذف، بررسی کنید. به جای myapp_pgdata، نام ولومی که در حال بررسی آن هستید را قرار دهید.

docker volume ls -f dangling=true
docker volume inspect myapp_pgdata
sudo ls -la /var/lib/docker/volumes/myapp_pgdata/_data

فیلتر dangling=true روی یک ولوم به معنای بدون ارجاع (unreferenced) است، نه خالی. لیست کردن _data به شما نشان می‌دهد که واقعاً چه چیزی در داخل آن وجود دارد. اگر یک دایرکتوری pgdata یا mysql در آن پیدا کردید، متوقف شوید و پیش از ادامه کار، یک کپی تهیه کنید. همین تخریب از طریق docker compose down -v نیز رخ می‌دهد که تمام ولوم‌های تعریف‌شده در فایل compose را حذف می‌کند و پیش از آن هیچ سؤالی از شما نمی‌پرسد.

ولوم تنها چیزی است که در یک میزبان Docker، با بازسازی (rebuild) قابل بازیابی نیست. به همین دلیل است که داده‌های ولوم باید در یک نسخه پشتیبان restic که خارج از سرور اجرا می‌شود قرار بگیرند، جایی که یک فلگ اشتباه تایپ‌شده نتواند به آن دسترسی پیدا کند.

وقتی هیچ‌چیز پاک نمی‌شود: فایل‌های لاگ کانتینر

شما همه چیز را پاکسازی کرده‌اید، docker system df تقریباً هیچ فضای قابل‌بازگشتی را نشان نمی‌دهد و دیسک همچنان پر است. لاگ‌ها را بررسی کنید.

sudo find /var/lib/docker/containers -name '*-json.log' -exec du -h {} + | sort -h | tail -10

هر کانتینر خروجی استاندارد و خطای استاندارد خود را در یک فایل JSON در مسیر /var/lib/docker/containers/ می‌نویسد. در نصب پیش‌فرض، max-size تنظیم نشده است که به معنای نامحدود بودن آن است؛ بنابراین یک کانتینر که در حلقهٔ crash گیر کرده باشد، تا زمانی که پارتیشن پر شود به نوشتن ادامه می‌دهد. هیچ دستور پاکسازی این فایل‌ها را حذف نمی‌کند، زیرا کانتینرهایی که آن‌ها را تولید می‌کنند در حال اجرا هستند و طبق تعریف، قابل پاکسازی نیستند.

فایل را حذف نکنید. اجرای rm روی یک فایل لاگ باز، هیچ فضایی را آزاد نمی‌کند، زیرا Docker daemon همچنان یک file descriptor باز نگه می‌دارد و هسته تا زمانی که آن handle بسته نشود، بلوک‌ها را تخصیص‌یافته نگه می‌دارد. df اصلاً تغییر نخواهد کرد. به‌جای آن، فایل را truncate کنید؛ این کار inode را ثابت نگه می‌دارد و به daemon اجازه می‌دهد به نوشتن ادامه دهد.

sudo find /var/lib/docker/containers -name '*-json.log' -exec truncate -s 0 {} +
df -h /

این یک راهکار موقت است. docker logs برای آن کانتینرها اکنون چیزی برنمی‌گرداند و فایل‌ها بلافاصله دوباره شروع به رشد می‌کنند. راهکار اصلی، چرخش لاگ (rotation) است که در بخش بعدی آمده است.

اندازه‌گیری قبل و بعد، همیشه

هرگز حدس نزنید که عملیات prune چه تغییری ایجاد کرده است. ابتدا یک اندازه‌گیری انجام دهید، دستور را اجرا کنید و سپس اندازه‌گیری مجدد را انجام دهید.

df -h /
docker system df
docker builder prune -f --filter until=168h
docker image prune -f
docker system df
df -h /

خروجی‌های df را با هم مقایسه کنید. این تنها عددی است که تعیین می‌کند آیا سرور شما به سرویس‌دهی ادامه می‌دهد یا خیر. سپس docker system df به شما می‌گوید که کدام ردیف واقعاً جابه‌جا شده است و هر عملیات prune، مقدار Total reclaimed space: مربوط به خود را چاپ می‌کند.

اگر df تغییری نکرد اما docker system df نشان می‌دهد که فضا آزاد شده است، یک file handle باز، بلوک‌های حذف‌شده را نگه داشته است که همان مشکل فایل لاگ ذکر شده در بالا است. اگر هر دو تغییر کردند و دیسک ظرف یک روز دوباره پر شد، شما با مشکل رشد داده‌ها مواجه هستید، نه مشکل پاک‌سازی؛ و راه‌حل آن چرخش لاگ‌ها (rotation) به همراه یک job زمان‌بندی‌شده است.

چگونه از پر شدن مجدد دیسک جلوگیری کنیم

محدود کردن حجم لاگ‌ها. فایل /etc/docker/daemon.json را ایجاد یا ویرایش کنید.

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

این تنظیم حجم لاگ هر کانتینر را به 30 MB محدود می‌کند. تمام مقادیر در log-opts باید به صورت رشته (string) باشند، حتی مقادیر عددی. پیش از راه‌اندازی مجدد، صحت فایل را بررسی کنید؛ زیرا یک daemon.json با فرمت نادرست باعث می‌شود daemon اصلاً اجرا نشود و تمام کانتینرها از دسترس خارج شوند.

python3 -m json.tool /etc/docker/daemon.json
sudo systemctl restart docker
docker info | grep -i 'logging driver'

docker info اکنون باید Logging Driver: json-file را گزارش دهد. محدودیت‌ها در بخش LogConfig از خروجی docker inspect برای کانتینرهایی که پس از راه‌اندازی مجدد ایجاد می‌شوند، قابل مشاهده خواهند بود؛ این نکته مهمی است: تنظیمات جدید فقط روی کانتینرهای تازه اعمال می‌شود. کانتینرهای موجود، پیکربندی زمان ساخت خود را حفظ می‌کنند، بنابراین باید آن‌ها را بازسازی (recreate) کنید.

docker compose up -d --force-recreate

همین محدودیت را می‌توان برای هر سرویس در فایل compose نیز اعمال کرد؛ این روش زمانی که یک سرویس پرمصرف نیاز به تنظیمات اختصاصی دارد، گزینه بهتری است.

services:
  app:
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

زمان‌بندی پاک‌سازی محدود. به‌صورت هفتگی، پاک‌سازی را فقط برای تصاویر معلق (dangling images) و کش قدیمی build انجام دهید. هرگز -a یا --volumes را در یک job زمان‌بندی‌شده قرار ندهید، زیرا اگر job در زمانی اجرا شود که یک stack خاموش است، تصاویر آن stack را حذف می‌کند و با وجود --volumes، شروع به پاک‌سازی داده‌های شما خواهد کرد.

sudo tee /etc/cron.weekly/docker-prune >/dev/null <<'EOF'
#!/bin/sh
docker image prune -f
docker builder prune -f --filter until=168h
EOF
sudo chmod +x /etc/cron.weekly/docker-prune
sudo /etc/cron.weekly/docker-prune

خط آخر، اسکریپت را یک بار به‌صورت دستی اجرا می‌کند تا پیش از اجرای خودکار، خروجی آن را مشاهده کنید. فایل باید قابل‌اجرا (executable) باشد و نام آن نباید حاوی نقطه باشد، زیرا run-parts هر فایلی که قابل‌اجرا نباشد یا پسوند داشته باشد را نادیده می‌گیرد.

هشدار برای فضای خالی. پاک‌سازی پس از پر شدن دیسک، یک اقدام برای بازیابی است. هشدار در سطح 80 درصد، یک اقدام پیشگیرانه است.

usage=$(df --output=pcent / | tr -dc '0-9')
[ "$usage" -ge 80 ] && echo "root filesystem at ${usage} percent full"

این دستور را در cron قرار دهید و از سیستم اطلاع‌رسانی فعلی خود استفاده کنید. فضای خالی تنها نیمی از تصویر است، بنابراین این هشدار را با پایش سلامت دیسک در VPS ترکیب کنید، زیرا خرابی دیسک و پر شدن دیسک هر دو باعث توقف کانتینرها می‌شوند اما هر کدام راهکار متفاوتی دارند.

تمام موارد بالا فرض را بر نصب استاندارد با مسیر داده در /var/lib/docker می‌گذارند. اگر آن را با کلید data-root در daemon.json تغییر داده‌اید، در تمام دستورات از مسیر خود استفاده کنید. تنظیم صحیح این ساختار در یک سرور تازه، بخشی از راه‌اندازی Docker روی VPS است و تصمیم‌گیری در مورد آن پیش از اینکه 40 GB کانتینر روی پارتیشن اشتباه داشته باشید، بسیار آسان‌تر است.

FAQ

آیا دستور docker system prune حجم‌های (volumes) من را حذف می‌کند؟

خیر. دستور سادهٔ آن فقط کانتینرهای متوقف‌شده، شبکه‌های بلااستفاده، ایمیج‌های معلق (dangling) و کش ساخت (build cache) بلااستفاده را حذف می‌کند و در اعلان تأیید، دقیقاً همین موارد فهرست می‌شوند. حجم‌ها تنها زمانی در محدودهٔ حذف قرار می‌گیرند که از فلگ --volumes استفاده کنید؛ و از نسخهٔ 23.0 موتور Docker به بعد، این فلگ فقط شامل حجم‌های بی‌نام (anonymous) می‌شود و نه حجم‌های نام‌گذاری‌شده. حجم‌های نام‌گذاری‌شده فقط با دستورات docker volume prune -a و docker compose down -v حذف می‌شوند. این دو دستور همان مواردی هستند که باید هنگام استفاده از آن‌ها دقت کنید.

چرا پس از اجرای docker prune هنوز دیسک من پر است؟

دو دلیل رایج برای این موضوع وجود دارد. دلیل اول فایل‌های لاگ کانتینر در مسیر /var/lib/docker/containers/ است که هیچ دستور prune به آن‌ها دسترسی ندارد و تا زمانی که max-size را تنظیم نکنید، بدون محدودیت رشد می‌کنند. دلیل دوم فایلی است که حذف شده اما یک پردازش همچنان آن را باز نگه داشته است: اگر فایلی را با rm در حالی که کانتینر در حال اجراست حذف کنید، دیمون (daemon) توصیف‌گر فایل (file descriptor) را نگه می‌دارد و کرنل بلوک‌های آن را آزاد نمی‌کند، بنابراین df تغییری در فضای آزاد گزارش نمی‌کند. خروجی sudo du -xh --max-depth=1 /var/lib/docker را با docker system df مقایسه کنید تا متوجه شوید با کدام مورد مواجه هستید.

تفاوت بین docker image prune و docker image prune -a چیست؟

دستور ساده فقط ایمیج‌های معلق (dangling) را حذف می‌کند؛ یعنی ایمیج‌هایی که تگ خود را از دست داده‌اند و معمولاً در اثر بازسازی (rebuild) ایجاد شده‌اند. فرم -a تمام ایمیج‌هایی را که هیچ کانتینری به آن‌ها ارجاع نمی‌دهد حذف می‌کند، از جمله ایمیج‌های تگ‌داری که خودتان عمداً دانلود (pull) کرده‌اید. پس از اجرای docker compose down، کانتینرها حذف می‌شوند، بنابراین -a ایمیج‌های مربوط به آن استک را نیز پاک می‌کند. هیچ‌چیز برای همیشه از دست نمی‌رود، زیرا در اجرای بعدی، ایمیج‌ها دوباره دانلود یا ساخته می‌شوند، اما در اتصالات اینترنت کند، این فرآیند زمان‌بر خواهد بود.

چگونه از پر شدن دیسک توسط لاگ‌های Docker جلوگیری کنم؟

گزینه‌های max-size و max-file را در بخش log-opts از فایل /etc/docker/daemon.json تنظیم کنید و سپس دیمون را با sudo systemctl restart docker راه‌اندازی مجدد کنید. این تنظیمات فقط برای کانتینرهایی اعمال می‌شود که پس از راه‌اندازی مجدد ایجاد شده‌اند، بنابراین کانتینرهای در حال اجرا را با docker compose up -d --force-recreate دوباره ایجاد کنید. می‌توانید همین دو گزینه را برای هر سرویس در فایل compose تحت کلید logging تنظیم کنید؛ این کار زمانی مفید است که یک سرویس خاص، لاگ‌های بسیار بیشتری نسبت به سایرین تولید می‌کند.

آیا اجرای docker system prune در cron job ایمن است؟

دستور سادهٔ docker system prune -f روی میزبانی که تمام استک‌ها در آن فعال هستند ایمن است، اما چون کانتینرهای متوقف‌شده را حذف می‌کند، ممکن است کانتینری را که عمداً متوقف کرده‌اید و قصد دارید بعداً دوباره اجرا کنید، از بین ببرد. یک برنامهٔ زمان‌بندی‌شدهٔ ایمن‌تر، استفاده از docker image prune -f به همراه docker builder prune -f --filter until=168h است که دو موردی را که سریع‌تر رشد می‌کنند پاکسازی کرده و به حجم‌ها دست نمی‌زند. هرگز -a یا --volumes را در برنامهٔ زمان‌بندی قرار ندهید.