Docker disk alanı temizleme ve prune komutları
VPS diskiniz Docker nedeniyle dolduysa hangi imaj, container veya volume verisinin yer kapladığını tespit edin. Veri kaybı yaşamadan disk alanını güvenli şekilde boşaltın.
Herhangi bir temizlik yapmadan önce disk alanını neyin kullandığını bulun
Docker, bir VPS üzerinde dört farklı noktada disk alanı kaplar: imajlar, durdurulmuş container'lar, derleme önbelleği (build cache) ve yerel volume'lar. Hangi kısmın alanı tükettiğini belirlemek için önce docker system df komutunu çalıştırın, ardından alanı boşaltacak en dar kapsamlı prune işlemini uygulayın. Sıralama önemlidir; çünkü bu kılavuzdaki son komut olan docker volume prune -a verileri siler ve bu işlemin geri dönüşü yoktur.
Docker ile değil, dosya sistemi ile başlayın.
df -h /
sudo du -xh --max-depth=1 /var/lib/docker | sort -hdf komutu durumun ne kadar kritik olduğunu gösterir. du ise alanın nereye gittiğini belirtir. -x bayrağı, du işlemini tek bir dosya sistemi üzerinde tutar; böylece ayrı bir volume'a yapılan mount işlemini takip etmez ve alanı mükerrer saymaz. Burada beş dizin önemlidir: overlay2 imaj ve container katmanlarını, volumes volume verilerini, containers container meta verilerini ve log dosyalarını, buildkit derleme önbelleğini ve image ise katman meta verilerini tutar.
sudo ve shell joker karakterleri (wildcard) hakkında bir not; çünkü bu durum çok zaman kaybettirir. /var/lib/docker dizininin sahibi root kullanıcısıdır ve normal kullanıcınız tarafından okunamaz; bu nedenle ls /var/lib/docker komutu Permission denied hatasını döndürür. sudo du -sh /var/lib/docker/* gibi bir komut da başarısız olur; çünkü shell, sudo çalışmadan önce * ifadesini genişletir ve shell'iniz bu dizini okuyamaz. Aşağıdaki her komut, tam da bu nedenle joker karakter yerine find veya --max-depth kullanır.
Şimdi Docker'ın kendi bakış açısına bakalım.
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.87GBBu rakamlar tek bir makineye aittir ve sizinkiler hakkında bir şey ifade etmez. Bunun yerine genel yapıya odaklanın. TOTAL nesneleri sayar, ACTIVE şu anda kullanımda olanları belirtir, RECLAIMABLE ise Docker'ın bir prune işlemiyle o satırdan ne kadar alan kazanılabileceğine dair tahminidir.
RECLAIMABLE ile ilgili iki husus kullanıcıları yanıltabilir. Paylaşılan imaj katmanlarını, onları kullanan her imaj için ayrı ayrı sayar; bu nedenle imaj satırı genellikle elde edeceğinizden daha fazla alan vaat eder. Ayrıca container log dosyalarını asla dahil etmez, çünkü Docker bir log dosyasını geri kazanılabilir bir nesne olarak görmez. du, docker system df komutunun belirttiğinden çok daha büyük bir dizin boyutu raporladığında, bunun sebebi log dosyalarıdır; bu konuyla ilgili bir bölüm aşağıda yer almaktadır.
Nesne bazlı döküm için -v ekleyin.
docker system df -vBu, özeti nesne türüne göre bölümlere ayırır. İmaj bölümü SHARED SIZE ve UNIQUE SIZE sütunlarını ekler, böylece tek bir imajın size gerçek maliyetini görebilirsiniz. Volume bölümü, o volume'a bağlı container sayısını gösteren bir LINKS sayacı ekler. LINKS değerini unutmayın; çünkü 0 değeri, volume prune komutlarının uygulanacağı temel kriterdir.
Dangling (askıda kalan) imajlar ile kullanılmayan imajlar
Bu iki terim birbirinin yerine kullanılabilecek gibi görünse de aslında farklıdır. Nesneler farklı olduğu için filtreler de farklı şekilde çalışır.
Dangling (askıda kalan) imaj, etiketi (tag) olmayan imajdır. <none> komutunun çıktısında docker images olarak görünür. Her yeniden derleme (rebuild) işleminde bir tane oluşturursunuz: docker build -t myapp:latest . komutu myapp:latest etiketini yeni imaja taşır; eski imaj tüm katmanlarını korur ancak ismini kaybeder. Hiçbir şey ona referans vermez ve sistem onu kendiliğinden temizlemez.
Kullanılmayan (unused) imaj ise, etiketli olsun ya da olmasın, şu anda hiçbir container tarafından referans verilmeyen her türlü imajdır. Geçen ay çektiğiniz ve şu an çalıştırmadığınız bir postgres:16 kullanılmayan imajdır, ancak askıda kalmış (dangling) değildir.
docker image prune # dangling images only
docker image prune -a # every image no container refers toİkincisi önce onay ister.
WARNING! This will remove all images without at least one container associated to them.
Are you sure you want to continue? [y/N]Bu istemi dikkatlice okuyun. "Associated to them" (onlarla ilişkili) ifadesi, çalışan veya durdurulmuş mevcut bir container nesnesini ifade eder. Eğer docker compose down komutunu çalıştırdıysanız container'lar silinmiştir; dolayısıyla bu servislerin kullandığı tüm imajlar artık kullanılmayan imaj konumuna düşer ve -a komutu hepsini siler. Geri getiremeyeceğiniz hiçbir şey kaybolmaz, ancak bir sonraki docker compose up -d komutu tümünü yeniden çeker veya derler; bu da küçük bir VPS üzerinde bant genişliği ve derleme süresi maliyeti yaratır. Herhangi bir temizlik (prune) işlemi yapmadan önce docker compose down komutunun neleri sildiği ve stop komutunun neleri çalışır durumda bıraktığı konusunu bilmek, pratik bir gerekliliktir.
Bir filtre, yakın zamanda oluşturulan imajları kapsam dışında tutar.
docker image prune -a --filter "until=240h"Bu komut, 240 saatten (10 gün) daha önce oluşturulmuş kullanılmayan imajları siler ve daha yeni olanlara dokunmaz. until değeri, 240h gibi bir Go süre dizisi veya 2026-08-01T00:00:00 gibi mutlak bir zaman damgası kabul eder.
Derleme önbelleği nedir ve neden sınırsız büyür
BuildKit, Docker Engine 23.0 sürümünden bu yana docker build ve docker compose build için Docker tarafından varsayılan olarak kullanılan derleyicidir. Çalıştırılan her Dockerfile dosyasının her adımının sonucunu önbelleğe alır ve bu önbelleği /var/lib/docker/buildkit dizininde tutar. İkinci derleme işleminizin saniyeler içinde tamamlanmasının nedeni bu önbellektir; yani sistem görevini yapmaktadır. Sorun, varsayılan olarak eski girdilerin süresinin dolmamasıdır. Her seferinde değişen bir COPY adımıyla aynı imajı elli kez derlerseniz, elli katman seti biriktirmiş olursunuz.
Derleme önbelleği docker image prune tarafından görünmez. Kendi komutuna sahip ayrı bir nesne türüdür.
docker builder prune # dangling cache
docker builder prune -a # all unused cache
docker builder prune --filter until=168h # cache untouched for 7 daysBunların hiçbiri imajlarınıza veya verilerinize dokunmaz. Derleme önbelleğini temizlemenin tek maliyeti, bir sonraki derleme işleminin bir defaya mahsus yavaş çalışmasıdır. İmajları düzenli olarak yeniden derleyen bir VPS üzerinde Build Cache, genellikle docker system df içindeki en büyük satırdır; bu da onu silinebilecek en güvenli büyük veri haline getirir.
Güvenli olandan yıkıcı olana doğru sıralanmış prune komutları
Bu listeyi yukarıdan aşağıya doğru takip edin ve df -h / tekrar sağlıklı göründüğünde durun. Her komut tamamlandığında bir Total reclaimed space: satırı yazdırır.
docker container prunedurdurulmuş container'ları kaldırır. Bunların yazılabilir katmanları da silinir; dolayısıyla bir container'ın volume dışında yazdığı her veri onunla birlikte silinir. Volume'lara dokunulmaz.docker image pruneyalnızca sahipsiz (dangling) imajları kaldırır. Bu, imajlar için mevcut olan en güvenli komuttur.docker builder prunesahipsiz build önbelleğini kaldırır. Bunun maliyeti bir adet yavaş build işlemidir.docker image prune -ahiçbir container tarafından referans verilmeyen tüm imajları kaldırır. Bunun maliyeti yeniden çekme (re-pull) veya yeniden build işlemidir.docker system pruneilk üç komutu aynı anda gerçekleştirir ve kullanılmayan ağları da ekler.docker volume prunekullanılmayan anonim volume'ları kaldırır.docker volume prune -aisimlendirilmiş olanlar dahil olmak üzere kullanılmayan tüm volume'ları kaldırır. Veritabanlarını silen komut budur.
docker system prune çalışmadan önce kendi kapsamını belirtir.
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'lar bu listeden kasıtlı olarak çıkarılmıştır. --volumes eklemek, anonim volume'ları tekrar kapsama dahil eder. -a eklemek, imaj adımı kapsamını sahipsiz imajlardan kullanılmayan tüm imajlara genişletir. Bir üretim sunucusunda tam kapsamlı docker system prune -a --volumes -f çalıştırmak, yer açmaya çalışırken veri kaybına yol açan bir işlemdir.
Hacim temizleme işlemi veritabanınızı neden siler
Bu bölümü iki kez okumalısınız.
Bir hacim, hiçbir container ona bağlı olmadığında kullanılmıyor olarak kabul edilir. Tek kriter budur. Docker, hacmin boş olup olmadığını, bir compose dosyasında tanımlı kalıp kalmadığını veya veritabanınızın tek kopyasını içerip içermediğini kontrol etmez. LINKS 0 ifadesi docker system df -v içinde yalnızca temizlenebilir anlamına gelir, başka hiçbir anlam taşımaz.
Şimdi birbirini takip eden iki sıradan işlemi ele alalım. Bir stack'i temiz bir şekilde yeniden başlatmak için docker compose down komutunu çalıştırırsınız. Bu komut container'ları kaldırır ve isimlendirilmiş hacimleri yerinde bırakır; bu, komutun dokümante edildiği şekilde çalışmasıdır. Postgres hacminiz artık hiçbir şeye bağlı değildir. On dakika sonra yer açmak için docker volume prune -a komutunu çalıştırırsınız ve veritabanı silinir. Her iki komut da beklendiği gibi çalışmıştır. Ancak bu sıralama verilerinizi yok etmiştir.
Docker Engine 23.0 (API sürümü 1.42) sürümünden itibaren, düz komut eskisinden daha kısıtlı bir kapsama sahiptir.
WARNING! This will remove anonymous local volumes not used by at least one container.Anonim bir hacim, genellikle bir image VOLUME bildirdiği ve siz ona bir isim vermediğiniz için Docker tarafından sizin adınıza oluşturulan hacimdir. Bunlar genellikle saklamanızı istemediğiniz verileri tutar. Compose dosyanıza yazdığınız türden isimlendirilmiş bir hacim, yalnızca -a eklediğinizde kaldırılır. Daha eski Docker sürümleri düz komutla her ikisini de kaldırıyordu, bu yüzden yükseltme yaptığınız bir sunucuda edindiğiniz alışkanlıklara güvenmeyin. Bu fark, ancak isimlendirilmiş hacimlerin bind mount'lardan nasıl farklı olduğunu bildiğinizde anlam kazanır; çünkü bir bind mount aslında bir Docker hacmi değildir ve hiçbir prune komutu ona dokunamaz.
Silmeden önce kontrol edin. myapp_pgdata komutundaki değeri kontrol ettiğiniz hacmin ismiyle değiştirin.
docker volume ls -f dangling=true
docker volume inspect myapp_pgdata
sudo ls -la /var/lib/docker/volumes/myapp_pgdata/_dataBir hacim üzerindeki dangling=true filtresi, hacmin boş olduğu anlamına değil, referanssız olduğu anlamına gelir. _data listesi, içerisinde gerçekte ne olduğunu gösterir. Eğer içerisinde bir pgdata veya mysql dizini bulursanız, durun ve daha ileri gitmeden önce bir kopyasını alın. Aynı yıkım, compose dosyasında tanımlanan her hacmi size sormadan kaldıran docker compose down -v komutuyla da gerçekleşir.
Bir hacim, Docker sunucusunda yeniden oluşturma işleminin geri getiremeyeceği tek şeydir. Bu nedenle hacim verileri, yanlış yazılmış bir flag'in erişemeyeceği sunucu dışında çalışan bir restic yedeği içerisinde tutulmalıdır.
Hiçbir şey temizlenemediğinde: container günlük dosyaları
Her şeyi temizlediyseniz, docker system df neredeyse hiçbir geri kazanılabilir alan göstermiyorsa ve disk hala doluysa günlükleri kontrol edin.
sudo find /var/lib/docker/containers -name '*-json.log' -exec du -h {} + | sort -h | tail -10Her container, standart çıktısını ve standart hata çıktısını /var/lib/docker/containers/ altındaki bir JSON dosyasına yazar. Varsayılan kurulumda max-size ayarlanmamıştır; bu, sınırsız olduğu anlamına gelir. Dolayısıyla, bir çökme döngüsüne giren tek bir container, bölüm dolana kadar yazmaya devam eder. Hiçbir prune komutu bu dosyaları silmez; çünkü bu dosyaları üreten container'lar çalışır durumdadır ve bu durum, onları tanım gereği temizlenemez kılar.
Dosyayı silmeyin. Açık bir günlük dosyası üzerinde rm çalıştırmak hiçbir alanı boşaltmaz; çünkü Docker daemon hala açık bir dosya tanımlayıcısını tutar ve kernel, o tutamaç kapanana kadar ilgili blokları tahsis edilmiş halde tutar. df hiçbir şekilde hareket etmeyecektir. Bunun yerine, aynı inode'u koruyan ve daemon'ın yazmaya devam etmesine olanak tanıyan truncate işlemini kullanın.
sudo find /var/lib/docker/containers -name '*-json.log' -exec truncate -s 0 {} +
df -h /Bu geçici bir çözümdür. Bu container'lar için docker logs artık hiçbir sonuç döndürmez ve dosyalar hemen tekrar büyümeye başlar. Asıl çözüm, bir sonraki bölümde yer alan döndürme (rotation) işlemidir.
Her zaman işlem öncesi ve sonrası ölçüm yapın
Bir temizleme işleminin ne yaptığını asla tahmin etmeyin. Bir ölçüm alın, tek bir komut çalıştırın ve tekrar ölçüm yapın.
df -h /
docker system df
docker builder prune -f --filter until=168h
docker image prune -f
docker system df
df -h /İki df çıktısını karşılaştırın. Sunucunuzun hizmet vermeye devam edip etmeyeceğine karar veren tek veri budur. docker system df, hangi satırın gerçekten değiştiğini gösterir ve her temizleme işlemi kendi Total reclaimed space: değerini yazdırır.
Eğer df değişmediği halde docker system df alanın boşaltıldığını söylüyorsa, açık bir dosya tanıtıcısı silinen blokları tutuyor demektir; bu, yukarıda bahsedilen günlük dosyası sorunudur. Eğer her ikisi de değiştiyse ve disk bir gün içinde tekrar doluyorsa, temizleme sorunu değil büyüme sorunu yaşıyorsunuz demektir; bu durumda çözüm, log rotasyonu ve zamanlanmış bir görevdir.
Diskin tekrar dolması nasıl önlenir
Log boyutunu sınırlayın. /etc/docker/daemon.json dosyasını oluşturun veya düzenleyin.
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}Bu ayar, her container için log boyutunu 30 MB ile sınırlar. log-opts altındaki tüm değerler, sayısal olanlar dahil olmak üzere, string (metin) biçiminde olmalıdır. Yeniden başlatmadan önce dosyanın ayrıştırılabilir olduğunu kontrol edin; hatalı bir daemon.json, daemon'ın hiç başlamamasına ve tüm container'ların devre dışı kalmasına neden olur.
python3 -m json.tool /etc/docker/daemon.json
sudo systemctl restart docker
docker info | grep -i 'logging driver'docker info artık Logging Driver: json-file değerini raporlamalıdır. Sınırların kendisi, yeniden başlatmadan sonra oluşturulan bir container'ın docker inspect çıktısındaki LogConfig bölümünde görünür; bu önemli bir detaydır: bu ayar yalnızca yeni oluşturulan container'lar için geçerlidir. Mevcut container'lar oluşturuldukları zamanki yapılandırmayı korurlar, bu nedenle onları yeniden oluşturmanız gerekir.
docker compose up -d --force-recreateAynı sınır, compose dosyasında servis bazında da tanımlanabilir; bu, çok fazla log üreten bir servisin kendi özel sınırına ihtiyaç duyduğu durumlarda daha iyi bir tercihtir.
services:
app:
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"Düzenli bir temizlik planlayın. Haftalık olarak, yalnızca kullanılmayan (dangling) imajları ve eski build önbelleğini hedefleyen bir temizlik yapın. -a veya --volumes komutlarını asla zamanlanmış bir işe dahil etmeyin; çünkü bir stack kapalıyken çalışan bir iş, o stack'in imajlarını siler ve --volumes ile birlikte verileriniz üzerinde işlem yapmaya başlar.
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-pruneSon satır, betiği manuel olarak bir kez çalıştırır; böylece betik gözetimsiz çalışmadan önce çıktısını görebilirsiniz. Dosya çalıştırılabilir olmalı ve isminde nokta karakteri bulunmamalıdır; çünkü run-parts, çalıştırılabilir olmayan veya uzantı taşıyan dosyaları atlar.
Boş alan için alarm kurun. Disk dolduktan sonra yapılan temizlik bir kurtarma işlemidir. Yüzde 80 doluluk oranında verilen bir uyarı ise önlemdir.
usage=$(df --output=pcent / | tr -dc '0-9')
[ "$usage" -ge 80 ] && echo "root filesystem at ${usage} percent full"Bunu, halihazırda kullandığınız bildirim aracıyla birlikte cron içine ekleyin. Boş alan resmin sadece yarısıdır; bu nedenle alarmı VPS üzerinde disk sağlığı izleme ile eşleştirin. Çünkü arızalanan bir disk ile dolu bir disk, container'larınızı durdurur ancak ikisi farklı çözüm yolları gerektirir.
Yukarıdaki her şey, veri kök dizininin /var/lib/docker olduğu standart bir kurulumu varsayar. Eğer bu dizini daemon.json içindeki data-root anahtarı ile taşıdıysanız, her komutta kendi yolunuzu kullanın. Bu düzeni yeni bir sunucuda doğru kurmak, VPS üzerinde Docker kurulumu sürecinin bir parçasıdır ve yanlış disk bölümünde 40 GB'lık container verisi birikmeden önce karar vermek çok daha kolaydır.
FAQ
docker system prune komutu volume dosyalarımı siler mi?
Hayır. Bu komutun yalın hali durdurulmuş container'ları, kullanılmayan ağları, sahipsiz (dangling) imajları ve kullanılmayan derleme önbelleğini siler; onay istemi de tam olarak bu öğeleri listeler. Volume'lar yalnızca --volumes parametresi eklendiğinde kapsama girer. Docker Engine 23.0 sürümünden itibaren bu parametre isimlendirilmiş volume'ları değil, yalnızca anonim volume'ları kapsar. İsimlendirilmiş volume'lar ise docker volume prune -a ve docker compose down -v komutları ile silinir. Dikkatli kullanılması gereken iki komut bunlardır.
docker prune çalıştırdıktan sonra diskim neden hala dolu?
Bunun genellikle iki sebebi vardır. Birincisi, /var/lib/docker/containers/ altındaki container log dosyalarıdır; hiçbir prune komutu bunlara dokunmaz ve siz max-size ayarını yapmadığınız sürece bu dosyalar sınırsız büyür. İkincisi ise bir sürecin hala açık tuttuğu silinmiş bir dosyadır: Eğer bir log dosyasını container çalışırken rm ile silerseniz, daemon dosya tanımlayıcısını (file descriptor) tutmaya devam eder ve çekirdek blokları serbest bırakmaz; bu yüzden df çıktısında bir değişiklik görülmez. Hangi durumla karşı karşıya olduğunuzu anlamak için sudo du -xh --max-depth=1 /var/lib/docker ile docker system df çıktılarını karşılaştırın.
docker image prune ile docker image prune -a arasındaki fark nedir?
Komutun yalın hali yalnızca sahipsiz (dangling) imajları, yani bir yeniden derleme sonucu etiketini kaybetmiş imajları siler. -a parametresi ise, mevcut hiçbir container tarafından referans verilmeyen tüm imajları; buna bilinçli olarak çektiğiniz etiketli imajlar da dahildir, siler. Bir docker compose down işleminden sonra container'lar silindiği için -a komutu o yığındaki imajları da beraberinde götürecektir. Hiçbir şey kalıcı olarak kaybolmaz, çünkü bir sonraki başlatmada imajlar yeniden çekilir veya derlenir; ancak yavaş bir bağlantıda bu uzun bir bekleme süresi anlamına gelir.
Docker loglarının diski doldurmasını nasıl engellerim?
/etc/docker/daemon.json dosyası içerisinde log-opts altında max-size ve max-file ayarlarını yapın, ardından daemon'ı sudo systemctl restart docker ile yeniden başlatın. Bu ayar yalnızca yeniden başlatmadan sonra oluşturulan container'lar için geçerli olacağından, çalışan container'ları docker compose up -d --force-recreate ile yeniden oluşturun. Aynı iki seçeneği bir compose dosyasında logging anahtarı altında servis bazlı olarak da tanımlayabilirsiniz; bir servis diğerlerinden çok daha fazla log üretiyorsa bu yöntem tercih edilmelidir.
Cron job içerisinde docker system prune çalıştırmak güvenli midir?
Yalın docker system prune -f komutu, tüm yığınların (stack) sürekli çalıştığı bir sunucuda güvenlidir. Ancak durdurulmuş container'ları sildiği için, daha sonra tekrar başlatmak üzere bilerek durdurduğunuz bir container'ı siler. Zamanlanmış görevler için daha güvenli olan yöntem, docker image prune -f ile birlikte docker builder prune -f --filter until=168h kullanmaktır; bu, en hızlı büyüyen iki alanı temizler ve volume'lara dokunmaz. -a veya --volumes komutlarını asla zamanlanmış görevlere eklemeyin.