توی این درس یاد میگیری داکر در طول زمان چه چیزهایی روی دیسک جمع میکند (کانتینرهای متوقف، image های بیصاحب، volume ها و کش build)، چطور با docker system df میزان فضا را میبینی و با docker image prune، docker system prune و docker volume prune تمیزش میکنی، و مهمتر: چه چیزی را هرگز بیفکر پاک نکنی. همهی دستورهای این درس روی یک daemon آزمایشی و ایزوله اجرا شدهاند تا داکر اصلیات دست نخورد.
تشبیه: انباری خانه
Section titled “تشبیه: انباری خانه”داکر مثل انباری است که هر بار چیزی میخری (image میگیری)، کار میکنی (کانتینر میسازی) یا چیزی ذخیره میکنی (volume)، به آن اضافه میشود. آدمها اغلب چیزهای بیمصرف را نگه میدارند: جعبههای خالی (کانتینر متوقف)، وسایلی که نسخهی جدیدشان آمده (image های قدیمی)، و پوشههای ناشناس. تمیزکاری لازم است، ولی باید بدانی کدام جعبهها خالیاند و کدام عکسهای خانوادگی (دادهی volume).
چه چیزهایی جمع میشود؟
Section titled “چه چیزهایی جمع میشود؟”مثالهای عملی
Section titled “مثالهای عملی”همهی مثالها داخل یک daemon آزمایشی هستند. اول یک وضعیت «شلوغ» میسازیم:
مثال ۱: ببین چقدر جا گرفته (docker system df)
Section titled “مثال ۱: ببین چقدر جا گرفته (docker system df)”docker system dfTYPE TOTAL ACTIVE SIZE RECLAIMABLEImages 3 1 13.62MB 23.29kB (0%)Containers 3 1 12.29kB 8.192kB (66%)Local Volumes 3 0 14B 14B (100%)Build Cache 5 0 13.54MB 12.29kBچهار ردیف: Images، Containers، Local Volumes و Build Cache. ستون RECLAIMABLE یعنی «چقدرش را میشود بدون آسیب به چیزهای در حال استفاده پاک کرد». برای جزئیات هر مورد -v را اضافه میکنی:
docker system df -v 2>/dev/null | head -14Images space usage:
REPOSITORY TAG IMAGE ID CREATED SIZE SHARED SIZE UNIQUE SIZE CONTAINERSlx-app latest fda8fde4ab76 4 seconds ago 13.5MB 13.5MB 11.72kB 0<none> <none> 31e7285c9ab6 6 seconds ago 13.5MB 13.5MB 11.58kB 0alpine latest 294b683cb724 2 weeks ago 13.6MB 13.5MB 87.52kB 3
Containers space usage:
CONTAINER ID IMAGE COMMAND LOCAL VOLUMES SIZE CREATED STATUS NAMES240eda947938 alpine "true" 0 4.1kB 3 seconds ago Exited (0) 2 seconds ago old221fdac2c6385 alpine "true" 0 4.1kB 3 seconds ago Exited (0) 2 seconds ago old15a5c907ecbaf alpine "sleep 600" 0 4.1kB 3 minutes ago Up 3 minutes live1مثال ۲: image های dangling
Section titled “مثال ۲: image های dangling”image ای که اسم و tag ندارد (مثلاً نتیجهی docker build . بدون -t، یا نسخهی قدیمیای که اسمش را از دست داده) dangling (آویزان) است. در این نسخهی داکر بهصورت پیشفرض در docker images دیده نمیشوند و باید فیلتر بدهی:
docker imagesecho "--- فقط dangling:"docker images -f dangling=trueIMAGE ID DISK USAGE CONTENT SIZE EXTRAalpine:latest 294b683cb724 13.6MB 4.28MB Ulx-app:latest fda8fde4ab76 13.5MB 4.19MB--- فقط dangling:IMAGE ID DISK USAGE CONTENT SIZE EXTRA<untagged> 31e7285c9ab6 13.5MB 4.19MBبدون فیلتر فقط alpine و lx-app (که اسم دارند) را میبینی، ولی فیلتر یک image با اسم <untagged> نشان میدهد؛ همان docker build . اولی. اینها بیصاحباند و پاک کردنشان امن است:
docker image prune -f | tail -1echo "dangling باقیمانده: $(docker images -f dangling=true -q | wc -l | tr -d ' ')"Total reclaimed space: 12.32kBdangling باقیمانده: 0مثال ۳: کانتینرهای متوقفشده
Section titled “مثال ۳: کانتینرهای متوقفشده”docker ps -a --format 'table {{.Names}}\t{{.Status}}'docker container prune -fecho "--- بعد از prune:"docker ps -a --format 'table {{.Names}}\t{{.Status}}'NAMES STATUSold2 Exited (0) 2 seconds agoold1 Exited (0) 3 seconds agolive1 Up 3 minutesDeleted Containers:240eda9479387d0814ea01e08ccbfc00e2f6770cf2703f709d63e13d8ae0ad0a21fdac2c6385638bca2c779c68ed184c54f3e7ba05404c75cd411b53be35355d
Total reclaimed space: 8.192kB--- بعد از prune:NAMES STATUSlive1 Up 3 minutesکانتینرهای old1 و old2 (متوقف) پاک شدند و live1 (در حال اجرا) دست نخورد. docker container prune هرگز کانتینر در حال اجرا را پاک نمیکند. میتوانی با --filter "until=24h" فقط قدیمیها را حذف کنی.
docker container prune کدام کانتینرها را حذف میکند؟
کانتینر در حال اجرا هرگز با prune حذف نمیشود.
مثال ۴: volume ها، جایی که باید دقت کنی
Section titled “مثال ۴: volume ها، جایی که باید دقت کنی”docker volume lsdocker volume prune -fecho "--- بعد از prune:"docker volume lsDRIVER VOLUME NAMElocal 41d6ccee33d53ac0bf32c7fd7e9b265e08e084e14a1c72a605cc05bdc0673965local importantlocal keepmeDeleted Volumes:41d6ccee33d53ac0bf32c7fd7e9b265e08e084e14a1c72a605cc05bdc0673965
Total reclaimed space: 0B--- بعد از prune:DRIVER VOLUME NAMElocal importantlocal keepmevolume ناشناس (با اسم طولانی هشمانند، که با -v /d ساخته شد و کانتینرش حذف شد) پاک شد، ولی volume نامدار keepme (که دادهی ارزشمندی داشت) ماند. از نسخههای جدید داکر، docker volume prune بهصورت پیشفرض فقط volume های ناشناس را حذف میکند و برای پاک کردن همهی volume های بدون کانتینر باید -a بدهی. ببین اگر -a بدهی چه میشود:
docker volume prune -a -fdocker volume lsDeleted Volumes:keepmeimportant
Total reclaimed space: 14BDRIVER VOLUME NAMEحالا keepme هم رفت، و با آن precious که داخلش بود. این پاک کردن برگشتپذیر نیست. (برای همین گفتیم قبل از -a مطمئن شو.)
مثال ۵: پاکسازی عمومی (docker system prune)
Section titled “مثال ۵: پاکسازی عمومی (docker system prune)”اگر بدون -f اجرا کنی، اول یک هشدار و درخواست تأیید میبینی. ببین چه چیزی قرار است پاک شود (من «n» میدهم تا چیزی پاک نشود):
docker run --rm alpine truedocker run --name old3 alpine true >/dev/nullecho n | docker system prune 2>&1 | head -9WARNING! 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]متن هشدار فهرست دستههای قابل پاک شدن را میگوید. بعد با -f (تأیید خودکار) اجرا میکنیم:
docker system prune -fDeleted Containers:09da0c11e69e5b79cae4b343b26c8c6139fe2ed97d77988e2fa904224894e0c0
Deleted build cache objects:jxk643n34rvothnh1lnbsqhahoz4lozpokb6yfnw4giepo3jjwkafkqjzmmlgss8m73n5ba1xqt
Total reclaimed space: 28.78kBدقت کن که این دستور volume ها را پاک نمیکند (مگر --volumes بدهی) و image های در حال استفاده هم دست نمیخورند. گزینهی -a علاوه بر dangling، همهی image های «بدون کانتینر» را هم پاک میکند.
مثال ۶: image های unused با -a و کش build
Section titled “مثال ۶: image های unused با -a و کش build”docker images --format 'table {{.Repository}}\t{{.Tag}}'docker image prune -a -fecho "--- بعد از prune -a:"docker images --format 'table {{.Repository}}\t{{.Tag}}'REPOSITORY TAGlx-app latestalpine latestDeleted Images:untagged: lx-app:latestdeleted: sha256:fda8fde4ab7695470c973df6035268db53cab310e7cac7b4c47c7d7e8a622ec6deleted: sha256:01aedb111fb5cf1351b0aa428b73b3ea44ea1c0771426690d118129f3bee30dcdeleted: sha256:2ab380819c686cb0656fa1beaa6428fdbb3b98613b56399c00b5d6c3378be721
Total reclaimed space: 12.47kB--- بعد از prune -a:REPOSITORY TAGalpine latestimage lx-app که هیچ کانتینری از آن نمیساخت پاک شد؛ ولی alpine که کانتینر live1 در حال استفاده از آن است ماند. و کش build:
docker builder prune -fdocker system df | head -2ID RECLAIMABLE SIZE LAST ACCESSEDxmjzy00wrf9k58vhiu4cxyj26 true 12.39kB 6 seconds agoTotal: 12.39kBTYPE TOTAL ACTIVE SIZE RECLAIMABLEImages 1 1 13.6MB 0B (0%)پشت پرده: «بیاستفاده» یعنی چه؟
Section titled “پشت پرده: «بیاستفاده» یعنی چه؟”داکر هر چیزی را از نظر ارجاع میسنجد:
- image dangling: بدون اسم و tag (
<none>). - image unused: هیچ کانتینری (حتی متوقف) از آن ساخته نشده.
- volume unused: هیچ کانتینری به آن وصل نیست.
- کانتینر: متوقفشده.
چون لایهها بین image ها مشترکاند، پاک کردن یک image فقط لایههایی را آزاد میکند که هیچ image دیگری استفاده نمیکند؛ پس مجموع RECLAIMABLE همیشه با جمع حجمهای روی کاغذ نمیخواند. و چون volume ها دادهی کاربر هستند، داکر آنها را جدا از بقیه حساب میکند.
جدولهای مرجع
Section titled “جدولهای مرجع”| دستور | چه چیزی را پاک میکند | ریسک |
|---|---|---|
docker container prune |
کانتینرهای متوقف | کم |
docker image prune |
image های dangling | کم |
docker image prune -a |
همهی image های بدون کانتینر | متوسط (دوباره دانلود) |
docker volume prune |
volume های ناشناس بیکانتینر | متوسط |
docker volume prune -a |
همهی volume های بیکانتینر | زیاد (داده) |
docker builder prune |
کش build | کم |
docker network prune |
شبکههای بدون استفاده | کم |
docker system prune |
کانتینر + image dangling + شبکه + کش | کم تا متوسط |
docker system prune -a --volumes |
کانتینر متوقف + همهی image های بدون کانتینر + volume های ناشناس | متوسط تا زیاد |
گزینههای مفید: -f (بدون سؤال)، --filter "until=24h" (فقط قدیمیتر از ۲۴ ساعت).
اشتباهات رایج
Section titled “اشتباهات رایج”۱) --volumes یا -a بدون فکر
Section titled “۱) --volumes یا -a بدون فکر”docker volume create important >/dev/nulldocker run --rm -v important:/d alpine sh -c 'echo data > /d/f'docker system prune -af --volumes >/dev/nullecho "بعد از system prune --volumes: $(docker volume ls -q | grep -c important)"docker volume prune -a -f >/dev/nullecho "بعد از volume prune -a: $(docker volume ls -q | grep -c important)"بعد از system prune --volumes: 1بعد از volume prune -a: 0system prune --volumes فقط volume های ناشناس را میبرد و important ماند؛ ولی docker volume prune -a آن را (چون کانتینری نداشت) برای همیشه پاک کرد. راهحل: -a را هیچوقت در اسکریپتهای خودکار نگذار؛ از volume های مهم جدا بکاپ بگیر.
۲) docker rm $(docker ps -aq) بهجای prune
Section titled “۲) docker rm $(docker ps -aq) بهجای prune”docker run -d --name keep1 alpine sleep 600 >/dev/nulldocker run --name gone1 alpine true >/dev/nulldocker rm $(docker ps -aq) 2>&1 | tail -3036648fe48a4Error response from daemon: cannot remove container "f5fd4c7cf056": container is running: stop the container before removing or force removeError response from daemon: cannot remove container "5a5c907ecbaf": container is running: stop the container before removing or force removeاین الگوی قدیمی همهی کانتینرها را هدف میگیرد؛ برای در حال اجرا خطا میدهد (و آنچه ممکن است حذف میکند). راهحل: docker container prune فقط متوقفشدهها را میگیرد.
۳) پاک کردن image در حال استفاده
Section titled “۳) پاک کردن image در حال استفاده”docker rmi alpine 2>&1 | head -2docker rm -f keep1 gone1 >/dev/nullError response from daemon: conflict: unable to delete alpine:latest (must be forced) - container f5fd4c7cf056 is using its referenced image 294b683cb724تا کانتینری از image استفاده میکند، docker rmi آن را پاک نمیکند (conflict). راهحل: اول کانتینر را حذف کن.
۴) تعجب از اینکه prune فضا را آزاد نکرد
Section titled “۴) تعجب از اینکه prune فضا را آزاد نکرد”چیزی که هنوز یک ارجاع دارد (یک کانتینر متوقف، یک image دیگر روی همان لایهها) آزاد نمیشود. با docker system df -v ببین چه چیزی هنوز به چه چیزی وصل است.
روی daemon آزمایشی وضعیت فضا را با docker system df نشان بده.
دیدن جواب
docker system dfTYPE TOTAL ACTIVE SIZE RECLAIMABLEImages 1 1 13.6MB 0B (0%)Containers 1 1 4.096kB 0B (0%)Local Volumes 0 0 0B 0BBuild Cache 0 0 0B 0Bتمرین اصلی: فضای داکر را بررسی و امن پاکسازی کن. دو کانتینر متوقف بساز، فهرستشان کن، فقط آنها را پاک کن و ثابت کن کانتینر در حال اجرا (runner) دست نخورد.
دیدن جواب
docker run -d --name runner alpine sleep 300 >/dev/nulldocker run --name s1 alpine true >/dev/nulldocker run --name s2 alpine true >/dev/nulldocker ps -a --format '{{.Names}}: {{.Status}}'docker container prune -f >/dev/nullecho "--- بعد:"docker ps -a --format '{{.Names}}: {{.Status}}'docker rm -f runner >/dev/nulls2: Exited (0) Less than a second agos1: Exited (0) Less than a second agorunner: Up 1 secondlive1: Up 3 minutes--- بعد:runner: Up 1 secondlive1: Up 4 minutesیک volume نامدار precious با فایلی داخلش بساز. ثابت کن docker volume prune -f (بدون -a) آن را پاک نمیکند، ولی docker volume prune -a -f پاکش میکند. بعد توضیح بده چرا برای سرور production هیچوقت نباید -a در اسکریپت خودکار باشد.
دیدن جواب
docker volume create precious >/dev/nulldocker run --rm -v precious:/d alpine sh -c 'echo data > /d/f'docker volume prune -f >/dev/nullecho "بعد از prune ساده: $(docker volume ls --format '{{.Name}}' | grep -c precious)"docker volume prune -a -f >/dev/nullecho "بعد از prune -a: $(docker volume ls --format '{{.Name}}' | grep -c precious)"بعد از prune ساده: 1بعد از prune -a: 0با -a هر volume ای که الان به کانتینری وصل نباشد حذف میشود، حتی اگر دادهی ارزشمند باشد؛ در یک اسکریپت خودکار ممکن است لحظهای که کانتینر دیتابیس متوقف است اجرا شود و داده را نابود کند.
آزمونک
Section titled “آزمونک”image «dangling» چیست؟
معمولاً image قدیمیای که tag اش به build جدید رفته.
docker system prune بهطور پیشفرض کدام را پاک نمیکند؟
volume ها فقط با --volumes پاک میشوند.
ستون RECLAIMABLE در docker system df یعنی…
پاک کردن آنها به کانتینرهای در حال اجرا آسیب نمیزند.
کدام دستور میتواند دادهی ارزشمند volume را برای همیشه پاک کند؟
prune -a همهی volume های بدون کانتینر را پاک میکند.
قبل از prune روی سرور واقعی اول چه کنی؟
اول بخوان چه چیزی هست و چقدر جا گرفته.
جمعبندی
Section titled “جمعبندی”- داکر کانتینر متوقف، image های dangling/unused، volume ها و کش build را جمع میکند؛ با
docker system dfببین. docker container pruneوdocker image pruneامناند؛docker image prune -aimage های بدون کانتینر را هم میبرد.- volume ها دادهی تو هستند:
docker volume pruneفقط ناشناسها را میبرد و-aهمهی بیکانتینرها را. docker system pruneکانتینر + dangling + شبکه + کش را پاک میکند؛--volumesفقط volume های ناشناس را میبرد و-aهمهی image های بدون کانتینر را.docker volume prune -aاست که volume های نامدار را هم میبرد.- همیشه اول بخوان، بعد پاک کن؛ و از volume های مهم بکاپ بگیر.
| دستور | کاری که میکند |
|---|---|
docker system df | خلاصهی فضای اشغالشده |
docker system df -v | جزئیات هر image/کانتینر/volume |
docker container prune -f | حذف کانتینرهای متوقف |
docker image prune -f | حذف image های dangling |
docker image prune -a -f | حذف همهی image های بدون کانتینر |
docker volume prune -f | حذف volume های ناشناس بیکانتینر |
docker volume prune -a -f | حذف همهی volume های بیکانتینر (خطرناک!) |
docker builder prune -f | پاک کردن کش build |
docker system prune -f | پاکسازی عمومی (بدون volume) |
docker system prune --filter "until=24h" | فقط چیزهای قدیمیتر از ۲۴ ساعت |