כשהדיסק של שרת Docker מתמלא, קונטיינרים נכשלים עם "no space left on device" ומסדי נתונים מפסיקים לכתוב, והרפלקס הרגיל, docker system prune, מוחק דברים בלי לומר אם הם בכלל הסיבה. האשף הזה מוצא קודם מה מחזיק את המקום: לוגים של קונטיינרים, images, build cache, volumes, מערכת הקבצים של קונטיינר עצמו, ה-journal של המערכת, קבצים שנמחקו ועדיין פתוחים, או inodes.
ענו על שאלה אחת בכל פעם. כל שלב מציג פקודה להרצה בשרת שלכם ומה הפלט שלה אומר; כל פקודה שמוחקת משהו אומרת מה היא מוחקת ומסומנת לפני שמריצים אותה. החליפו את <container>, <service>, <volume> ו-<mount> בשמות שלכם. העמוד לא מריץ שום דבר ולא שולח דבר לשום מקום; התשובות נשמרות בקישור של העמוד, אף פעם לא הפלט שלכם.
מוצאים את הסיבה, צעד אחר צעד
איזו מערכת קבצים מלאה?
מתחילים מהמספרים שהקרנל מדווח לכל מערכת קבצים מחוברת. דיסק מלא מציג Use% של 100% או קרוב לזה, וכמעט כלום תחת Avail; אז קונטיינרים נכשלים עם no space left on device, מסדי נתונים מפסיקים לכתוב, ו-Docker עצמו עלול לסרב להפעיל קונטיינרים.
Docker שומר את הנתונים שלו תחת /var/lib/docker, אלא אם ה-data-root שלו הועבר; ברוב השרתים זו מערכת הקבצים הראשית /. אם לא בטוחים איפה זה, docker info --format "{{.DockerRootDir}}" מדפיס את הנתיב, ובכל פקודה בהמשך מחליפים את /var/lib/docker בנתיב הזה.
df -hכל השלבים כטקסט
אותו עץ כמו באשף שלמעלה, כל הענפים בבת אחת, לקריאה או להדפסה.
הצגת כל השאלות, הבדיקות והפתרונות של האשף
איזו מערכת קבצים מלאה?
מתחילים מהמספרים שהקרנל מדווח לכל מערכת קבצים מחוברת. דיסק מלא מציג Use% של 100% או קרוב לזה, וכמעט כלום תחת Avail; אז קונטיינרים נכשלים עם no space left on device, מסדי נתונים מפסיקים לכתוב, ו-Docker עצמו עלול לסרב להפעיל קונטיינרים.
Docker שומר את הנתונים שלו תחת /var/lib/docker, אלא אם ה-data-root שלו הועבר; ברוב השרתים זו מערכת הקבצים הראשית /. אם לא בטוחים איפה זה, docker info --format "{{.DockerRootDir}}" מדפיס את הנתיב, ובכל פקודה בהמשך מחליפים את /var/lib/docker בנתיב הזה.
df -hתשובות
- מערכת הקבצים שמחזיקה את הנתונים של Docker (לרוב /) ב-100% או קרוב לזה: עוברים אל “המקום אצל Docker, בלוגים, או במקום אחר?”
- רק מערכת קבצים אחרת מלאה (למשל /boot או /home): עוברים אל “המקום נמצא מחוץ ל-Docker”
- אף אחת לא קרובה ל-100%, ובכל זאת כתיבה נכשלת עם "no space left on device": עוברים אל “האם נגמרו ה-inodes?”
האם נגמרו ה-inodes?
למערכת קבצים יש שתי מגבלות: בתים ו-inodes. כל קובץ וכל תיקייה תופסים inode אחד, וכשהם נגמרים אי אפשר ליצור קובץ חדש, גם כשיש גיגה-בתים פנויים. מיליוני קבצים קטנים (שכבות של images, build cache, תיקיית cache של אפליקציה, קובצי session) גומרים את ה-inodes הרבה לפני שהם ממלאים את הבתים.
df -i מציג את אותן מערכות קבצים בספירת inodes; הסתכלו על IUse% במערכת הקבצים שבה הכתיבה נכשלת.
df -iתשובות
- IUse% ב-100% או קרוב לזה: עוברים אל “במערכת הקבצים נגמרו ה-inodes”
- IUse% רחוק מ-100%: עוברים אל “אף ענף לא התאים: אוספים את מה שצריך כדי להמשיך לחפור”
המקום אצל Docker, בלוגים, או במקום אחר?
לפני שמוחקים משהו, מוצאים מי מחזיק את המקום. הפקודה סוכמת את שלושת החשודים הרגילים: תיקיית הנתונים של Docker, זו של containerd (שבה ה-image store של containerd שומר את נתוני ה-images), ולוגי המערכת תחת /var/log. תיקייה שלא קיימת בשרת שלכם מדולגת בשקט.
השוו את הגדלים לעמודת Used ש-df -h הציג לאותה מערכת קבצים. du קורא כל קובץ, ולכן בתיקייה גדולה זה יכול לקחת דקה.
sudo du -sh /var/lib/docker /var/lib/containerd /var/log 2>/dev/nullתשובות
- /var/lib/docker (או /var/lib/containerd) מחזיק את רוב המקום התפוס: עוברים אל “איפה בתוך הנתונים של Docker?”
- /var/log מחזיק את רובו: עוברים אל “האם זה ה-journal של המערכת?”
- ביחד הם מחזיקים הרבה פחות ממה ש-df מציג כתפוס: עוברים אל “מוצאים את התיקיות הגדולות ביותר”
מוצאים את התיקיות הגדולות ביותר
המקום נמצא מחוץ ל-Docker ומחוץ ללוגים. הציגו את התיקיות הגדולות ביותר במערכת הקבצים המלאה, שתי רמות לעומק; -x משאיר את du באותה מערכת קבצים ולא סופר מערכות קבצים אחרות שמחוברות מתחתיה.
אם גם התיקיות הגדולות ביותר מסתכמות בהרבה פחות מ-Used, את המקום מחזיקים קבצים שנמחקו אבל עדיין פתוחים: du כבר לא רואה אותם, והקרנל עדיין סופר אותם.
sudo du -xh --max-depth=2 / 2>/dev/null | sort -h | tail -n 15תשובות
- תיקייה מחוץ ל-Docker ומחוץ ללוגים גדולה: עוברים אל “המקום נמצא מחוץ ל-Docker”
- התיקיות מסתכמות בהרבה פחות מה-Used של df: עוברים אל “קבצים שנמחקו עדיין פתוחים”
איפה בתוך הנתונים של Docker?
תיקיית הנתונים של Docker מתחלקת לפי סוג: containers מחזיקה את ההגדרות של כל קונטיינר ואת קובץ הלוג שלו, overlay2 מחזיקה שכבות של images, את השכבות הניתנות לכתיבה של הקונטיינרים ואת ה-build cache, ו-volumes מחזיקה את הנתונים של volumes עם שם ובלי שם. הגדולה מביניהן מצביעה על הסיבה.
הפקודה מציגה את הרמה הראשונה של /var/lib/docker, מהקטנה לגדולה. אם המקום נמצא דווקא תחת /var/lib/containerd, נתוני ה-images וה-build cache נמצאים שם.
sudo du -h --max-depth=1 /var/lib/docker | sort -hתשובות
- containers הכי גדולה: עוברים אל “האם הלוגים של הקונטיינרים הם הסיבה?”
- overlay2 הכי גדולה, או שהמקום נמצא תחת /var/lib/containerd: עוברים אל “מה Docker עצמו סופר?”
- volumes הכי גדולה: עוברים אל “אילו volumes, והאם משתמשים בהם?”
האם הלוגים של הקונטיינרים הם הסיבה?
עם ה-logging driver ברירת המחדל json-file, Docker כותב כל מה שקונטיינר מדפיס לקובץ ליד ההגדרות שלו, וכברירת מחדל הוא אף פעם לא מגלגל ולא מגביל את הקובץ הזה. קונטיינר פטפטן אחד יכול לכתוב גיגה-בתים ביום. docker system df לא סופר את הקבצים האלה, ולכן קל לפספס אותם.
הפקודה רצה כ-root בתוך shell כי רק root יכול לקרוא את תיקיית הקונטיינרים; היא מציגה את חמשת קובצי הלוג הגדולים ביותר. שם התיקייה בכל נתיב הוא ה-ID המלא של הקונטיינר.
sudo sh -c 'du -h /var/lib/docker/containers/*/*-json.log' | sort -h | tail -n 5תשובות
- קובץ *-json.log אחד או יותר גדולים: עוברים אל “הלוגים של הקונטיינרים לא עוברים רוטציה”
- קובצי הלוג קטנים, או שאין כאלה (logging driver אחר): עוברים אל “מה Docker עצמו סופר?”
מה Docker עצמו סופר?
docker system df סוכם את האובייקטים של Docker עצמו בארבע שורות: images, קונטיינרים (השכבות הניתנות לכתיבה שלהם), volumes מקומיים וה-build cache. RECLAIMABLE הוא מה שאף קונטיינר לא משתמש בו כרגע ואפשר להסיר.
בחרו את השורה שמחזיקה הכי הרבה. RECLAIMABLE גדול ב-images או ב-build cache הוא המקרה הקל; שורת Containers גדולה אומרת שקונטיינר כותב למערכת הקבצים של עצמו במקום ל-volume.
docker system dfתשובות
- Images, עם RECLAIMABLE גדול: עוברים אל “images ישנים ושלא בשימוש ממלאים את הדיסק”
- Build Cache: עוברים אל “ה-build cache ממשיך לגדול”
- Containers: עוברים אל “קונטיינר כותב למערכת הקבצים של עצמו”
- Local Volumes: עוברים אל “אילו volumes, והאם משתמשים בהם?”
- אף שורה לא גדולה, או שה-images גדולים אבל שום דבר לא ניתן לפינוי: עוברים אל “אף ענף לא התאים: אוספים את מה שצריך כדי להמשיך לחפור”
אילו volumes, והאם משתמשים בהם?
volume חי יותר מהקונטיינר שיצר אותו: הסרת קונטיינר, או docker compose down בלי -v, משאירה את ה-volumes שלו במקום. לאורך חודשים, stacks של בדיקות וגרסאות ישנות משאירים volumes שאף קונטיינר לא משתמש בהם, וחלק מהם מחזיקים נתונים אמיתיים.
הצורה המפורטת מציגה כל volume עם הגודל שלו ועם LINKS, מספר הקונטיינרים שמשתמשים בו. LINKS שהוא 0 אומר שאף קונטיינר, רץ או עצור, לא משתמש ב-volume כרגע; זה לא אומר שהנתונים בו חסרי ערך.
docker system df -vתשובות
- volumes גדולים עם LINKS 0 (אף קונטיינר לא משתמש בהם): עוברים אל “volumes שאף קונטיינר לא משתמש בהם”
- את ה-volume הגדול משמש קונטיינר שאני מריץ: עוברים אל “הנתונים של שירות רץ ממשיכים לגדול”
האם זה ה-journal של המערכת?
בשרתים עם systemd, הדייר הגדול ביותר ב-/var/log הוא בדרך כלל ה-journal ב-/var/log/journal. הוא שומר את הפלט של כל שירות, וכברירת מחדל הוא יכול לגדול עד 10% ממערכת הקבצים (עד 4 GB ל-journal), ובדיסק קטן או מלא כבר זה מקום שצריך.
הפקודה מדפיסה כמה מקום תופסים קובצי ה-journal הפעילים והישנים. היא רק קוראת.
sudo journalctl --disk-usageתשובות
- ה-journal תופס כמה גיגה-בתים: עוברים אל “ה-journal של המערכת גדול מדי”
- ה-journal קטן; קבצים אחרים ב-/var/log גדולים: עוברים אל “קובצי לוג ב-/var/log לא עוברים רוטציה ולא נמחקים”
הלוגים של הקונטיינרים לא עוברים רוטציה
ה-driver json-file שומר כל שורה שקונטיינר הדפיס מאז שנוצר. התיקון הקבוע הוא מגבלת גודל: max-size ו-max-file ל-json-file, או ה-driver local, שמגלגל ודוחס כברירת מחדל. מגבלה שמוגדרת ב-daemon.json חלה רק על קונטיינרים שנוצרים אחרי השינוי, ולכן צריך ליצור מחדש את הקונטיינרים הקיימים.
ריקון קובץ לוג מפנה את המקום מיד, ומוחק את היסטוריית הלוג של אותו קונטיינר: כל מה שהלוג החזיק, כולל השורות שמסבירות תקלה קודמת, נעלם. העתיקו קודם את הסוף שלו אם ייתכן שתצטרכו אותו.
מה לעשות
- התאימו את ה-ID בנתיב של הלוג הגדול ביותר לשם של קונטיינר.
docker ps -a --no-trunc --format "{{.ID}} {{.Names}}" - קראו קודם את השורות האחרונות, והעתיקו את מה שייתכן שתצטרכו: השלב הבא מוחק אותן.
docker logs --tail 200 <container> - רוקנו את קובץ הלוג של הקונטיינר. זה מוחק את כל היסטוריית הלוג שלו; הקונטיינר ממשיך לרוץ ולכתוב לאותו קובץ.
sudo truncate -s 0 "$(docker inspect --format '{{.LogPath}}' <container>)" - הגבילו את הלוגים לתמיד: הגדירו
log-driverל-local, אוjson-fileעםlog-optsשלmax-size(למשל10m) ו-max-file(למשל3), ב-/etc/docker/daemon.json, או לכל שירות תחתlogging:בקובץ ה-Compose. - אחרי שינוי
daemon.json, הפעילו מחדש את Docker כדי שיקרא את הקובץ. כל הקונטיינרים נעצרים ועולים שוב (אלה שיש להם restart policy).sudo systemctl restart docker - צרו מחדש את הקונטיינרים כדי שהגדרות הלוג החדשות יחולו עליהם. נתונים ב-volumes נשארים; כל מה שקונטיינר כתב למערכת הקבצים של עצמו אובד.
docker compose up -d --force-recreate - בדקו כמה מקום התפנה.
df -h
images ישנים ושלא בשימוש ממלאים את הדיסק
כל docker pull של גרסה חדשה משאיר את הישנה. image תלוי (<none> ברשימה) הוא גרסה ישנה שהתג שלה עבר הלאה; image שלא בשימוש הוא כזה שאף קונטיינר, רץ או עצור, לא נוצר ממנו. עדכון stacks לאורך חודשים משאיר גיגה-בתים משניהם.
docker image prune מסיר רק images תלויים. עם -a הוא מסיר כל image שאף קונטיינר קיים לא משתמש בו, כולל כאלה שאולי תרצו שוב: הם לא אובדים לתמיד, רק נמשכים שוב בהפעלה הבאה, וזה דורש שה-registry יהיה זמין ושהתג עדיין יהיה קיים.
מה לעשות
- הציגו את ה-images ואת הגדלים שלהם.
docker image ls - הסירו images תלויים. זה מוחק רק גרסאות ישנות בלי תג.
docker image prune - אם זה לא מספיק, הסירו כל image שאף קונטיינר לא משתמש בו. קונטיינרים עצורים שומרים על ה-images שלהם; stack שהורדתם עם
docker compose downימשוך את ה-images שלו מחדש.docker image prune -a - בדקו כמה מקום התפנה.
df -h
ה-build cache ממשיך לגדול
כל docker build ו-docker compose build שומרים את השכבות ואת הקבצים שהורדו ב-build cache, כדי שה-build הבא יהיה מהיר יותר. בשרת שבונה images בעצמו (CI runner, deploy שבונה על השרת), ה-cache גדל עם כל שינוי, ורק ה-garbage collection שלו מגביל אותו.
הסרת build cache אף פעם לא נוגעת ב-images, בקונטיינרים או ב-volumes: ה-build הבא איטי יותר, כי הוא מתחיל בלי cache.
מה לעשות
- הציגו מה ה-cache מחזיק.
docker buildx du - הסירו cache שלא היה בשימוש בשבוע האחרון. זה מוחק build cache בלבד.
docker builder prune --filter until=168h - או הסירו את כולו, אם הדיסק עדיין מלא.
docker builder prune -a - שמרו עליו מעכשיו עם מגבלות ה-garbage collection של ה-builder ב-
daemon.json(ההגדרות שלbuilder.gc). - בדקו כמה מקום התפנה.
df -h
קונטיינר כותב למערכת הקבצים של עצמו
כל מה שקונטיינר כותב מחוץ ל-volumes שלו נכנס לשכבה הניתנת לכתיבה שלו תחת overlay2: העלאות, cache, לוגים לקובץ, מסד נתונים בלי volume. הנתונים האלה גדלים כל עוד הקונטיינר קיים, ונמחקים יחד איתו, ולכן זו גם בעיית דיסק וגם סיכון לאובדן נתונים.
התיקון הוא למצוא את הנתיב שהאפליקציה כותבת אליו ולשים אותו על volume. גם קונטיינרים עצורים שכבר לא צריך מחזיקים את השכבות שלהם.
מה לעשות
- הציגו את הקונטיינרים עם הגודל של השכבה הניתנת לכתיבה שלהם (
SIZE).docker ps -a -s --format "{{.Names}} {{.Size}}" - בדקו אילו קבצים הגדול מביניהם הוסיף או שינה (
Aו-C).docker diff <container> | head -n 50 - חברו את הנתיב הזה כ-volume בקובץ ה-Compose (
volumes:של השירות), אחרי שהעתקתם ממנו כל מה שצריך עםdocker cp. - צרו מחדש את השירות עם ה-volume. השכבה הניתנת לכתיבה הישנה שלו, וכל קובץ בה, נמחקים.
docker compose up -d --force-recreate <service> - הסירו קונטיינרים עצורים שכבר לא צריך. זה מוחק כל קונטיינר עצור ואת השכבה הניתנת לכתיבה שלו, לא volumes.
docker container prune - בדקו כמה מקום התפנה.
df -h
volumes שאף קונטיינר לא משתמש בהם
volume שלא בשימוש יכול להיות שאריות של נתוני בדיקה, או העותק היחיד של מסד נתונים שה-stack שלו למטה כרגע. הסרת volume מוחקת את הנתונים שלו לתמיד; שום פקודת Docker לא מחזירה אותם. הסתכלו בתוך כל אחד, וגבו את מה שאתם לא בטוחים בו לפני שאתם מסירים.
docker volume prune מסיר רק volumes אנונימיים שלא בשימוש (מאז Docker Engine 23); עם -a הוא מסיר גם כל volume עם שם שלא בשימוש. העדיפו להסיר לפי שם את ה-volumes שבדקתם.
מה לעשות
- הציגו את ה-volumes שאף קונטיינר לא משתמש בהם.
docker volume ls --filter dangling=true - בדקו איזה פרויקט Compose יצר volume (התוויות שלו) ומתי.
docker volume inspect <volume> - הסתכלו מה הוא מחזיק.
sudo ls -la /var/lib/docker/volumes/<volume>/_data - גבו כל volume שייתכן שתצטרכו את הנתונים שלו, לפני שאתם מסירים אותו.
- הסירו volume שבדקתם. הנתונים שלו נמחקים לתמיד.
docker volume rm <volume> - או הסירו בבת אחת כל volume אנונימי שלא בשימוש. קונטיינרים שהופעלו בלי volume עם שם (image של מסד נתונים עם
VOLUME) שומרים את הנתונים שלהם בדיוק ב-volumes כאלה: בדקו קודם את הרשימה שלמעלה.docker volume prune - בדקו כמה מקום התפנה.
df -h
הנתונים של שירות רץ ממשיכים לגדול
המקום שייך לאפליקציה שאתם מריצים: מסד הנתונים שלה, העלאות, מדיה, או גיבויים שהיא כותבת ל-volume של עצמה. שום דבר ב-Docker לא אמור להימחק כאן; הניקוי קורה באפליקציה (מדיניות שמירה, גיבויים ישנים, vacuum של מסד הנתונים) או במתן דיסק גדול יותר לנתונים.
מצאו איזו תיקייה בתוך ה-volume גדלה, ואז השתמשו בדרך המתועדת של האפליקציה עצמה כדי לנקות אותה. מחיקת קבצים מתחת למסד נתונים שרץ משחיתה אותו.
מה לעשות
- בדקו איזו תיקייה בתוך ה-volume גדולה.
sudo du -h --max-depth=2 /var/lib/docker/volumes/<volume>/_data | sort -h | tail -n 10 - אם אלה גיבויים או ייצואים שהאפליקציה כותבת, העבירו אותם אל מחוץ לשרת והגדירו כמה מהם היא שומרת.
- אם זה מסד הנתונים עצמו, השתמשו בניקוי המתועד שלו (למשל הגדרות שמירה או vacuum), אף פעם לא
rmעל הקבצים שלו. - אם הנתונים פשוט גדולים מהדיסק, תכננו דיסק גדול יותר או העברה של ה-
data-rootשל Docker לדיסק כזה; האשף הזה לא מכסה הגדלת דיסק אצל ספק.
ה-journal של המערכת גדול מדי
ה-journal מוחק רשומות ישנות רק כשהוא מגיע למגבלה שלו, ומגבלת ברירת המחדל היא חלק ממערכת הקבצים, לא גודל קבוע. vacuum מוחק את קובצי ה-journal הישנים ביותר עד לגודל שנותנים לו; הקובץ הפעיל נשמר, כך שהרשומות האחרונות נשארות.
אחר כך הגדירו מגבלה קבועה, כדי שה-journal לא יוכל למלא את הדיסק שוב: SystemMaxUse= ב-/etc/systemd/journald.conf, שנכנס לתוקף אחרי הפעלה מחדש של journald.
מה לעשות
- מחקו את קובצי ה-journal הישנים ביותר עד שה-journal תופס לכל היותר 500 MB. לוגים ישנים של המערכת נעלמים אחרי זה.
sudo journalctl --vacuum-size=500M - הגבילו אותו: הגדירו
SystemMaxUse=500Mבחלק[Journal]של/etc/systemd/journald.conf. - הפעילו מחדש את journald כדי שיקרא את המגבלה החדשה. הרישום נעצר לרגע.
sudo systemctl restart systemd-journald - ודאו את הגודל.
sudo journalctl --disk-usage
קובצי לוג ב-/var/log לא עוברים רוטציה ולא נמחקים
רוב השירותים שכותבים לוגים לקבצים סומכים על logrotate שישנה שם, ידחוס ובסוף ימחק קבצים ישנים. שירות בלי כלל logrotate, או כזה שמתעלם ממנו, מגדיל קובץ אחד בלי סוף; עותקים מגולגלים (.1, .gz) מצטברים כשמספר העותקים שנשמרים גבוה.
מצאו קודם את הקבצים הגדולים. הסרת עותקים דחוסים ישנים מפנה מקום בלי לגעת במה ששירותים כותבים עכשיו.
מה לעשות
- הציגו את הקבצים והתיקיות הגדולים ביותר תחת /var/log.
sudo du -ah /var/log 2>/dev/null | sort -h | tail -n 15 - מחקו לוגים מגולגלים ודחוסים שישנים מ-30 יום. הם נעלמים לתמיד.
sudo find /var/log -type f -name "*.gz" -mtime +30 -delete - בדקו מה logrotate היה עושה, בלי לעשות את זה, כדי למצוא קובץ שאף כלל לא מכסה.
sudo logrotate --debug /etc/logrotate.conf - הוסיפו כלל לקובץ הזה ב-
/etc/logrotate.d/(עםsize, rotateו-compress), או גרמו לשירות לכתוב ל-journal במקום. - בדקו כמה מקום התפנה.
df -h
קבצים שנמחקו עדיין פתוחים
מחיקת קובץ מסירה את השם שלו, אבל הקרנל משחרר את המקום שלו רק כשהתהליך האחרון שמחזיק אותו פתוח סוגר אותו. קובץ לוג שנמחק ידנית בזמן ששירות עדיין כותב אליו ממשיך לגדול בלי שרואים: df סופר אותו, du לא מוצא אותו.
lsof +L1 מציג קבצים פתוחים שכבר אין להם שם, עם התהליך שמחזיק כל אחד. הפעלה מחדש של התהליך הזה, או של הקונטיינר שהוא רץ בו, משחררת את המקום.
מה לעשות
- הציגו קבצים שנמחקו ועדיין פתוחים, עם הגודל והתהליך שלהם (התקינו
lsofאם הוא חסר).sudo lsof -nP +L1 - אם התהליך הוא שירות מערכת, הפעילו אותו מחדש. השירות נעצר לרגע.
sudo systemctl restart <service> - אם הוא רץ בקונטיינר, הפעילו מחדש את הקונטיינר הזה.
docker restart <container> - בפעם הבאה, רוקנו לוג שתהליך עדיין כותב אליו במקום למחוק אותו, או תנו ל-logrotate לטפל בו.
- בדקו כמה מקום התפנה.
df -h
במערכת הקבצים נגמרו ה-inodes
inodes מתפנים רק במחיקת קבצים, ולכן התיקון הוא למצוא את התיקייה עם הכי הרבה קבצים. בשרת Docker זו הרבה פעמים overlay2 (הרבה images, או build cache עם הרבה שכבות קטנות); במקומות אחרים זה cache, תור דואר או קובצי session של אפליקציה.
אם הספירה נמצאת בתיקייה של Docker, הסרת images ו-build cache שלא בשימוש מפנה inodes באותה דרך שהיא מפנה בתים.
מה לעשות
- ספרו קבצים לכל תיקייה, שלוש רמות לעומק, במערכת הקבצים המלאה.
sudo du --inodes -x --max-depth=3 / 2>/dev/null | sort -n | tail -n 10 - אם זה תחת /var/lib/docker: הסירו images תלויים (רק גרסאות ישנות בלי תג).
docker image prune - וגם build cache שישן משבוע (רק build cache).
docker builder prune --filter until=168h - אם זה במקום אחר, נקו את התיקייה הזו עם הכלי של האפליקציה שהיא שלה.
- בדקו שוב את ה-inodes.
df -i
המקום נמצא מחוץ ל-Docker
Docker הוא לא מה שממלא את מערכת הקבצים הזו: זו תיקייה של המערכת או של משתמש, כמו גיבויים ישנים, הורדות, תיקיית בית, או kernels ישנים ב-/boot קטן. prune של אובייקטים של Docker היה מוחק דברים בלי לפנות את המקום הזה.
הציגו את התיקיות הגדולות ביותר במערכת הקבצים הזו והסירו רק מה שאתם יודעים שכבר לא צריך; לחבילות ול-kernels השתמשו במנהל החבילות של ההפצה שלכם, לא ב-rm.
מה לעשות
- הציגו את התיקיות הגדולות ביותר במערכת הקבצים המלאה; החליפו את
<mount>בנקודת החיבור שלה מתוךdf -h.sudo du -xh --max-depth=2 <mount> 2>/dev/null | sort -h | tail -n 15 - העבירו גיבויים וארכיונים ישנים אל מחוץ לשרת לפני שאתם מוחקים אותם כאן.
- ל-kernels ישנים ול-cache של חבילות, השתמשו במנהל החבילות של ההפצה שלכם.
אף ענף לא התאים: אוספים את מה שצריך כדי להמשיך לחפור
התשובות עד עכשיו לא מצביעות על מקום אחד. אספו את התמונה המלאה לפני שמוחקים משהו: המקום וה-inodes בכל מערכת קבצים, מה Docker סופר, איפה Docker שומר את הנתונים שלו, ומה הקרנל אמר כשהכתיבה נכשלה. זה גם מה שפורום או מעקב באגים יבקשו.
כל הפקודות כאן רק קוראות. docker info מדפיס את הגדרות השרת בלי סודות; ובכל זאת עברו על כל פלט לפני ששולחים אותו למישהו.
מה לעשות
- מקום ו-inodes בכל מערכת קבצים.
df -h && df -i - הספירה של Docker עצמו, לכל image, קונטיינר ו-volume.
docker system df -v - איפה Docker שומר את הנתונים שלו, ומה ה-storage driver וה-logging driver שלו.
docker info --format "{{.DockerRootDir}} {{.Driver}} {{.LoggingDriver}}" - הגודל של התיקיות של Docker ושל המערכת.
sudo du -sh /var/lib/docker /var/lib/containerd /var/log 2>/dev/null - הודעות הקרנל מהשעה האחרונה (שגיאות של מערכת קבצים, חיבור מחדש לקריאה בלבד).
journalctl -k --since "1 hour ago"
מה לא מכוסה כאן
האשף מכסה שרת Linux יחיד עם Docker Engine וה-storage ברירת המחדל overlay2. Docker Desktop שומר את הנתונים שלו בתוך דיסק וירטואלי, ו-nodes של Kubernetes מנקים images ולוגים דרך ה-kubelet; שניהם עובדים אחרת. הגדלת דיסק או volume אצל ספק לא מכוסה.
הסרת volume מוחקת את הנתונים שלו לתמיד, וריקון לוג מוחק את ההיסטוריה שלו: קראו כל פקודה מסומנת לפני שאתם מריצים אותה, וגבו את מה שאתם לא בטוחים בו. כשאף ענף לא מתאים, השלב האחרון מפרט מה לאסוף; הוא לא מנחש.
עמודים קשורים
מקורות
- Docker Docs: JSON File logging driver
- Docker Docs: Local file logging driver
- Docker Docs: Configure logging drivers
- Docker Docs: Configure the daemon (daemon.json)
- Compose file reference: logging
- Docker Docs: docker image prune
- Docker Docs: Prune unused Docker objects
- Docker Docs: docker system df
- Docker Docs: docker builder prune
- Docker Docs: Build garbage collection
- Docker Docs: Storage
- Docker Docs: docker container diff
- Docker Docs: docker container ls
- Docker Docs: docker container prune
- Docker Docs: Volumes
- Docker Docs: docker volume rm
- Docker Docs: docker volume prune
- du(1), Linux manual page
- journalctl(1), systemd manual
- journald.conf(5), systemd manual
- logrotate (project and manual)
- unlink(2), Linux manual page
- df(1), Linux manual page
- Docker Docs: docker system info
האופן שבו ANAROQ מתעד מקורות לעובדות שבעמודים שלו מתואר במתודולוגיה. למתודולוגיה