Docker prune: VPS वरील डिस्क जागा कशी मोकळी करावी
VPS ची डिस्क भरली आहे? images, containers, build cache किंवा volumes पैकी जागा कोण घेत आहे ते शोधा आणि डेटा न गमावता योग्य Docker prune चालवा.
काहीही prune करण्यापूर्वी डिस्क जागा कोण वापरत आहे ते शोधा
Docker VPS वर चार ठिकाणी डिस्क जागा वापरतो: images, stopped containers, build cache आणि local volumes. जागा यापैकी कोणत्या घटकाने व्यापली आहे हे शोधण्यासाठी प्रथम docker system df चालवा. त्यानंतर तेवढाच भाग साफ करणारा सर्वात मर्यादित prune चालवा. क्रम महत्त्वाचा आहे, कारण या मार्गदर्शकातील शेवटची कमांड, docker volume prune -a, डेटा हटवते आणि तो पूर्ववत करता येत नाही.
Docker पासून सुरुवात करू नका. प्रथम filesystem तपासा.
df -h /
sudo du -xh --max-depth=1 /var/lib/docker | sort -hdf समस्या किती गंभीर आहे ते दाखवते. du जागा कुठे वापरली गेली ते दाखवते. -x flag मुळे du एकाच filesystem वर मर्यादित राहते. त्यामुळे ते mount मधून वेगळ्या volume मध्ये जात नाही आणि जागा दोनदा मोजली जात नाही. येथे पाच directories महत्त्वाच्या आहेत: overlay2 मध्ये image आणि container layers असतात, volumes मध्ये volume data असतो, containers मध्ये container metadata आणि log files असतात, buildkit मध्ये build cache असतो आणि image मध्ये layer metadata असतो.
sudo आणि shell wildcards बाबत एक महत्त्वाची नोंद आहे, कारण यामुळे अनेकदा बराच वेळ वाया जातो. /var/lib/docker चे मालक root आहे आणि तुमच्या सामान्य user ला ते वाचता येत नाही. त्यामुळे ls /var/lib/docker चे output Permission denied येते. sudo du -sh /var/lib/docker/* सारखी कमांडही अपयशी ठरते, कारण sudo चालण्यापूर्वीच तुमचा shell * expand करतो आणि तुमचा shell ती directory वाचू शकत नाही. याच कारणासाठी खालील प्रत्येक कमांड wildcard ऐवजी find किंवा --max-depth वापरते.
आता Docker चे स्वतःचे दृश्य पाहू.
docker system dfTYPE 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 objects मोजते, ACTIVE सध्या वापरात असलेले objects मोजते आणि RECLAIMABLE त्या row मधून prune केल्यास किती जागा मोकळी होऊ शकते याचा Docker चा अंदाज दाखवते.
RECLAIMABLE बाबत दोन गोष्टी लक्षात ठेवा. एकाच shared image layer चा वापर करणाऱ्या प्रत्येक image साठी तो layer एकदा मोजला जातो. त्यामुळे image row मध्ये दाखवलेली संभाव्य मोकळी जागा प्रत्यक्षात मिळणाऱ्या जागेपेक्षा सहसा जास्त असते. तसेच container log files यामध्ये कधीही समाविष्ट नसतात, कारण Docker log file ला reclaimable object मानत नाही. du एखादी directory docker system df मध्ये दाखवलेल्या आकारापेक्षा खूप मोठी दाखवत असेल, तर त्याचे कारण log files असतात. त्यासाठी खाली स्वतंत्र section आहे.
प्रत्येक object चा सविस्तर breakdown पाहण्यासाठी -v जोडा.
docker system df -vयामुळे summary object type नुसार स्वतंत्र section मध्ये विभागली जाते. Image section मध्ये SHARED SIZE आणि UNIQUE SIZE columns जोडले जातात. त्यामुळे एका image मुळे प्रत्यक्षात किती जागा वापरली जाते ते पाहता येते. Volume section मध्ये LINKS count जोडला जातो. हा त्या volume शी जोडलेल्या containers ची संख्या असते. LINKS लक्षात ठेवा, कारण value 0 असणे हीच volume prune commands लागू करण्यासाठीची संपूर्ण चाचणी आहे.
dangling images आणि unused images
हे दोन शब्द एकसारखे वाटतात; पण ते समान नाहीत. Objects वेगवेगळे असल्यामुळे filters चे वर्तनही वेगळे असते.
dangling image म्हणजे tag नसलेली image. ती docker images मध्ये <none> म्हणून दिसते. प्रत्येक rebuild वेळी अशी image तयार होते: docker build -t myapp:latest . नवीन image वर myapp:latest tag हलवते आणि जुन्या image कडे तिचे सर्व layers राहतात; पण तिचे नाव निघून जाते. तिचा संदर्भ कोणताही object घेत नाही आणि ती आपोआप clean up होत नाही.
unused image म्हणजे सध्या कोणताही container ज्याचा संदर्भ घेत नाही अशी कोणतीही image. मागील महिन्यात pull केलेली आणि सध्या चालू नसलेली postgres:16 unused आहे; पण ती dangling नाही.
docker image prune # dangling images only
docker image prune -a # every image no container refers toदुसरी command आधी पुष्टी विचारते.
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" याचा अर्थ चालू किंवा थांबवलेला existing container object असा आहे. तुम्ही docker compose down चालवले असल्यास containers हटवले जातात. त्यामुळे त्या services ने वापरलेल्या सर्व images आता unused होतात आणि -a त्या सर्व हटवते. परत मिळवता न येणारे काहीही नष्ट होत नाही; पण पुढील docker compose up -d वेळी त्या सर्व images पुन्हा pull किंवा rebuild केल्या जातात. लहान VPS वर यासाठी bandwidth आणि build time लागतो. त्यामुळे prune करण्यापूर्वी docker compose down काय हटवते आणि stop काय चालू ठेवते हे जाणून घेणे उपयुक्त ठरते.
filter मुळे अलीकडील images वगळल्या जातात.
docker image prune -a --filter "until=240h"ही command 240 तासांपेक्षा (10 दिवसांपेक्षा) जुन्या unused images हटवते आणि नवीन images तशाच ठेवते. until value मध्ये 240h सारखी Go duration string किंवा 2026-08-01T00:00:00 सारखा absolute timestamp वापरता येतो.
build cache म्हणजे काय आणि तो मर्यादेशिवाय का वाढतो
Docker Engine 23.0 पासून docker build आणि docker compose build साठी Docker ने BuildKit हा builder default म्हणून वापरला आहे. तो चालवलेल्या प्रत्येक Dockerfile मधील प्रत्येक step चा परिणाम cache करतो आणि हा cache /var/lib/docker/buildkit मध्ये ठेवतो. दुसरी build काही सेकंदांत पूर्ण होते, याचे कारण हा cache आहे. त्यामुळे तो अपेक्षेप्रमाणे काम करत आहे. समस्या अशी आहे की जुन्या entries default म्हणून आपोआप expire होत नाहीत. प्रत्येक वेळी बदलणाऱ्या COPY step सह तीच image पन्नास वेळा build केली, तर layers चे पन्नास संच साठून राहतात.
build cache docker image prune ला दिसत नाही. तो स्वतंत्र command असलेला वेगळा object type आहे.
docker builder prune # dangling cache
docker builder prune -a # all unused cache
docker builder prune --filter until=168h # cache untouched for 7 daysयापैकी कोणतीही गोष्ट तुमच्या images किंवा data ला स्पर्श करत नाही. build cache साफ केल्याची एकमेव किंमत म्हणजे पुढील build एकदा हळू चालते. नियमितपणे images rebuild करणाऱ्या VPS वर Build Cache हे अनेकदा docker system df मधील सर्वात मोठे row असते. त्यामुळे हटवण्यासाठी ते सर्वात सुरक्षित मोठे घटक ठरते.
सुरक्षित ते विनाशकारी अशा क्रमाने prune commands
या यादीत वरून खाली जा आणि df -h / पुन्हा व्यवस्थित दिसू लागल्यावर लगेच थांबा. प्रत्येक command पूर्ण झाल्यावर Total reclaimed space: line दाखवतो.
docker container pruneथांबवलेले containers काढून टाकतो. त्यांचे writable layers देखील काढले जातात. त्यामुळे volume च्या बाहेर container ने लिहिलेली कोणतीही माहिती त्यासोबत हटवली जाते. Volumes वर कोणताही परिणाम होत नाही.docker image pruneफक्त dangling images काढून टाकतो. हा उपलब्ध असलेला सर्वात सुरक्षित image command आहे.docker builder prunedangling build cache काढून टाकतो. याची किंमत म्हणजे एकदा build धीम्या गतीने चालेल.docker image prune -aकोणताही container वापरत नसलेली प्रत्येक image काढून टाकतो. यामुळे image पुन्हा pull करावी किंवा पुन्हा build करावी लागेल.docker system pruneपहिले तीन कामे एकाच वेळी करतो आणि वापरात नसलेले networks देखील काढून टाकतो.docker volume pruneवापरात नसलेले anonymous volumes काढून टाकतो.docker volume prune -anamed volumes सहित वापरात नसलेले volumes काढून टाकतो. Databases हटवणारा हा command आहे.
docker system prune चालण्यापूर्वी त्याची scope स्वतः सांगतो.
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]Volumes या यादीत जाणीवपूर्वक समाविष्ट केलेले नाहीत. --volumes जोडल्यास anonymous volumes देखील scope मध्ये येतात. -a जोडल्यास image step dangling images पासून सर्व unused images पर्यंत विस्तृत होतो. Production host वर पूर्ण docker system prune -a --volumes -f चालवल्यामुळे space मोकळी करण्याच्या प्रयत्नात data गमावले जाऊ शकते.
व्हॉल्यूम prune केल्याने तुमचा database का हटतो
हा विभाग दोनदा वाचा.
कोणताही container त्याला जोडलेला नसल्यास volume वापरात नसलेला मानला जातो. हीच संपूर्ण तपासणी आहे. volume रिकामा आहे का, compose file मध्ये तो अजून घोषित केला आहे का किंवा त्यात database ची एकमेव प्रत आहे का, हे Docker तपासत नाही. LINKS 0 ला docker system df -v मध्ये prune करण्यायोग्य मानले जाते. याचा अर्थ एवढाच आहे.
आता दोन सामान्य कृती सलग करा. Stack स्वच्छपणे restart करण्यासाठी तुम्ही docker compose down चालवता. यामुळे containers हटतात आणि named volumes तिथेच राहतात. हेच त्या command च्या दस्तऐवजीकरणानुसार अपेक्षित आहे. तुमचा Postgres volume आता कोणत्याही container ला जोडलेला नाही. दहा मिनिटांनी जागा मोकळी करण्यासाठी तुम्ही docker volume prune -a चालवता आणि database हटतो. दोन्ही commands ने योग्य प्रकारे काम केले. मात्र या क्रमामुळे data नष्ट झाला.
Docker Engine 23.0 (API version 1.42) पासून plain command पूर्वीपेक्षा अधिक मर्यादित आहे.
WARNING! This will remove anonymous local volumes not used by at least one container.Anonymous volume हे Docker ने तुमच्यासाठी तयार केलेले volume असते. साधारणपणे image मध्ये VOLUME घोषित केलेले असते आणि तुम्ही त्याला नाव दिलेले नसते. अशा volume मध्ये सहसा तुम्ही जतन करण्यास सांगितलेला नसलेला data असतो. तुम्ही compose file मध्ये लिहिलेला named volume -a जोडल्यावरच हटवला जातो. जुन्या Docker versions मध्ये plain command दोन्ही प्रकारचे volumes हटवत असे. त्यामुळे नंतर upgrade केलेल्या host वरील जुन्या सवयींवर विश्वास ठेवू नका. named volumes bind mounts पेक्षा कसे वेगळे आहेत हे समजल्यानंतरच हा फरक स्पष्ट होतो. कारण bind mount हा Docker volume नसतो आणि कोणताही prune command त्याला कधीही स्पर्श करणार नाही.
हटवण्यापूर्वी तपासा. तपासत असलेल्या volume च्या नावासाठी myapp_pgdata बदला.
docker volume ls -f dangling=true
docker volume inspect myapp_pgdata
sudo ls -la /var/lib/docker/volumes/myapp_pgdata/_dataVolume वरील dangling=true filter चा अर्थ unreferenced असा आहे; empty असा नाही. _data दाखवल्यास त्यामध्ये प्रत्यक्षात काय आहे ते दिसते. त्यात pgdata किंवा mysql directory आढळल्यास थांबा आणि पुढे जाण्यापूर्वी तिची प्रत घ्या. docker compose down -v मुळेही हाच data नष्ट होतो. हा command compose file मध्ये घोषित केलेला प्रत्येक volume हटवतो आणि आधी तुमची परवानगी मागत नाही.
Docker host वरील असा एकमेव घटक म्हणजे volume, जो rebuild केल्यावर पुन्हा तयार करता येत नाही. म्हणून volume data server च्या बाहेर चालणाऱ्या restic backup मध्ये असणे आवश्यक आहे. चुकीचा flag वापरल्यामुळे त्या backup पर्यंत पोहोचून data नष्ट होऊ नये.
काहीही prune होत नसताना: container log files
तुम्ही सर्वकाही prune केले आहे, docker system df मध्ये reclaim करता येण्यासारखे जवळजवळ काहीही दिसत नाही, आणि disk अजूनही full आहे. Logs तपासा.
sudo find /var/lib/docker/containers -name '*-json.log' -exec du -h {} + | sort -h | tail -10प्रत्येक container त्याचे standard output आणि standard error /var/lib/docker/containers/ अंतर्गत JSON file मध्ये लिहितो. Default install मध्ये max-size unset असते. त्यामुळे त्याची मर्यादा नसते. Crash loop मध्ये अडकलेला एकच container partition full होईपर्यंत लिहित राहू शकतो. कोणताही prune command या files काढत नाही. कारण त्या files तयार करणारे containers चालू असतात आणि व्याख्येनुसार ते prunable नसतात.
File delete करू नका. Open log file वर rm चालवल्याने काहीही मोकळी जागा मिळत नाही. Docker daemon कडे open file descriptor कायम असतो आणि तो handle बंद होईपर्यंत kernel ते blocks allocated ठेवतो. df मध्ये कोणताही बदल होणार नाही. त्याऐवजी file truncate करा. त्यामुळे तोच inode कायम राहतो आणि daemon लेखन सुरू ठेवू शकतो.
sudo find /var/lib/docker/containers -name '*-json.log' -exec truncate -s 0 {} +
df -h /हा तात्पुरता उपाय आहे. त्या containers साठी docker logs आता काहीही परत करत नाही, आणि files पुन्हा लगेच वाढू लागतात. खरा उपाय म्हणजे rotation. तो पुढील section मध्ये आहे.
प्रत्येक वेळी आधी आणि नंतरचे मोजमाप घ्या
prune ने काय केले याचा कधीही अंदाज लावू नका. आधी एक मोजमाप घ्या, एक command चालवा आणि नंतर पुन्हा मोजमाप घ्या.
df -h /
docker system df
docker builder prune -f --filter until=168h
docker image prune -f
docker system df
df -h /दोन्ही df outputs ची तुलना करा. तुमचा server सेवा देत राहतो की नाही हे ठरवणारा एकमेव आकडा हाच आहे. त्यानंतर docker system df मधून नेमकी कोणती row बदलली ते कळते आणि प्रत्येक prune स्वतःचा Total reclaimed space: आकडा दाखवते.
df मध्ये बदल झाला नाही, पण docker system df मध्ये space मोकळी झाल्याचे दिसत असेल, तर deleted blocks एखादा open file handle धरून ठेवत आहे. हीच वर स्पष्ट केलेली log file ची समस्या आहे. दोन्हीमध्ये बदल झाला आणि एक दिवसाच्या आत disk पुन्हा भरली, तर ही cleanup ची समस्या नसून वाढीची समस्या आहे. अशा वेळी rotation आणि scheduled job आवश्यक आहेत.
डिस्क पुन्हा भरू नये यासाठी काय करावे
लॉगचा आकार मर्यादित करा. /etc/docker/daemon.json तयार करा किंवा संपादित करा.
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}यामुळे प्रत्येक कंटेनरसाठी लॉगचा आकार 30 MB पर्यंत मर्यादित होतो. log-opts अंतर्गत प्रत्येक मूल्य string असणे आवश्यक आहे; संख्यात्मक मूल्येदेखील त्याला अपवाद नाहीत. रीस्टार्ट करण्यापूर्वी फाइलचे parsing योग्यरीत्या होते का ते तपासा. चुकीचा 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 दिसले पाहिजे. रीस्टार्टनंतर तयार केलेल्या कंटेनरमध्ये मर्यादा docker inspect च्या LogConfig विभागात दिसतात. हा महत्त्वाचा तपशील आहे: ही सेटिंग फक्त नवीन कंटेनरना लागू होते. विद्यमान कंटेनर त्यांच्या निर्मितीच्या वेळी असलेली configuration ठेवतात. त्यामुळे ते पुन्हा तयार करा.
docker compose up -d --force-recreateहीच मर्यादा compose file मधील प्रत्येक service साठी स्वतंत्रपणे देता येते. एखाद्या जास्त लॉग निर्माण करणाऱ्या service साठी वेगळी मर्यादा आवश्यक असेल, तेव्हा हा अधिक योग्य पर्याय आहे.
services:
app:
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"मर्यादित prune schedule करा. हे साप्ताहिक चालवा आणि फक्त dangling images आणि जुना build cache यांच्यापुरते मर्यादित ठेवा. Scheduled job मध्ये -a किंवा --volumes कधीही ठेवू नका. Stack बंद असताना job चालल्यास त्या stack च्या images हटवल्या जातील. --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शेवटची ओळ script एकदा manually चालवते. त्यामुळे ती unattended पद्धतीने चालण्यापूर्वी तिचे output पाहता येते. फाइल executable असणे आवश्यक आहे. तिच्या नावात dot नसावा, कारण run-parts non-executable फाइल्स आणि extension असलेल्या फाइल्स वगळते.
मोकळ्या डिस्क जागेवर alarm लावा. डिस्क भरल्यानंतर केलेला prune हा recovery उपाय आहे. 80 percent वर दिलेला alert हा प्रतिबंधात्मक उपाय आहे.
usage=$(df --output=pcent / | tr -dc '0-9')
[ "$usage" -ge 80 ] && echo "root filesystem at ${usage} percent full"तुम्ही आधीपासून वापरत असलेल्या notifier सह हे cron मध्ये जोडा. मोकळी जागा ही समस्येची फक्त अर्धी बाजू आहे. त्यामुळे हा alarm तुमच्या VPS वरील डिस्क health monitoring सोबत वापरा. बिघडणारी डिस्क आणि पूर्ण भरलेली डिस्क दोन्ही तुमचे कंटेनर बंद पाडतात; मात्र त्यांच्यासाठी वेगवेगळे उपाय आवश्यक असतात.
वरील सर्व सूचना /var/lib/docker येथे data root असलेल्या standard install गृहीत धरतात. daemon.json मधील data-root key वापरून data root हलवला असल्यास, प्रत्येक command मध्ये तुमचा path वापरा. नवीन box वर ही layout योग्यरीत्या ठरवणे हे VPS वर Docker सेट करण्याचा भाग आहे. चुकीच्या partition वर 40 GB चे कंटेनर साठल्यानंतर निर्णय घेण्यापेक्षा हे आधी ठरवणे खूप सोपे असते.
FAQ
docker system prune माझे volumes हटवते का?
नाही. साधी command थांबवलेले containers, न वापरलेले networks, dangling images आणि न वापरलेला build cache हटवते. तिच्या confirmation prompt मध्ये नेमका हाच संच दाखवला जातो. तुम्ही --volumes जोडल्यावरच volumes विचारात घेतले जातात. Docker Engine 23.0 पासून हा flag named volumes ऐवजी anonymous volumes वर लागू होतो. Named volumes docker volume prune -a आणि docker compose down -v द्वारे हटवले जातात. या दोन commands वापरताना विशेष काळजी घ्या.
docker prune चालवल्यानंतरही माझी disk भरलेली का आहे?
याची दोन सामान्य कारणे आहेत. पहिले कारण म्हणजे /var/lib/docker/containers/ अंतर्गत असलेल्या container log files. कोणतीही prune command त्यांना स्पर्श करत नाही. max-size सेट करेपर्यंत त्या मर्यादेशिवाय वाढतात. दुसरे कारण म्हणजे process ने अजूनही open ठेवलेली deleted file. Container चालू असताना तुम्ही rm ने एखादी log हटवली, तर daemon file descriptor उघडा ठेवतो. त्यामुळे kernel blocks मुक्त करत नाही आणि df मध्ये कोणताही बदल दिसत नाही. तुमच्याकडे यापैकी कोणते कारण आहे हे पाहण्यासाठी sudo du -xh --max-depth=1 /var/lib/docker ची तुलना docker system df सोबत करा.
docker image prune आणि docker image prune -a यांच्यात काय फरक आहे?
साधी command फक्त dangling images हटवते. म्हणजे ज्या images चा tag निघून गेला आहे, सामान्यतः rebuild मुळे, अशा images. -a form कोणताही existing container ज्याचा संदर्भ देत नाही अशा सर्व images हटवते. यात तुम्ही जाणीवपूर्वक pull केलेल्या tagged images देखील येतात. docker compose down नंतर containers हटवले जातात. त्यामुळे -a त्या stack मधील images देखील हटवेल. काहीही कायमचे गमावले जात नाही, कारण पुढील start वेळी त्या images पुन्हा pull किंवा rebuild केल्या जातात. मात्र link धीमा असल्यास यासाठी बराच वेळ लागू शकतो.
Docker logs मुळे disk भरू नये यासाठी काय करावे?
/etc/docker/daemon.json मध्ये log-opts अंतर्गत max-size आणि max-file सेट करा. त्यानंतर sudo systemctl restart docker वापरून daemon restart करा. हे setting त्या restart नंतर तयार केलेल्या containers वरच लागू होते. त्यामुळे चालू containers docker compose up -d --force-recreate वापरून पुन्हा तयार करा. Compose file मधील logging key अंतर्गत प्रत्येक service साठी हेच दोन options सेट करता येतात. एखादी service इतरांपेक्षा खूप जास्त logs निर्माण करत असल्यास हा पर्याय उपयुक्त ठरतो.
cron job मध्ये docker system prune चालवणे सुरक्षित आहे का?
साधी docker system prune -f अशा host वर सुरक्षित आहे जिथे प्रत्येक stack सतत चालू राहतो. मात्र ती stopped containers हटवते. त्यामुळे तुम्ही जाणीवपूर्वक थांबवलेला आणि नंतर पुन्हा सुरू करायचा असलेला container देखील हटवला जाईल. अधिक सुरक्षित scheduled job म्हणजे docker image prune -f आणि docker builder prune -f --filter until=168h. यामुळे सर्वात वेगाने वाढणाऱ्या दोन बाबींची साफसफाई होते आणि कोणत्याही volume ला स्पर्श होत नाही. -a किंवा --volumes कधीही schedule करू नका.