Docker to wspaniałe narzędzie. I straszny bałaganiarz.

Każdy docker pull, każdy build, każdy kontener, który kiedyś uruchomiłeś i zatrzymałeś, zostawia po sobie ślad na dysku. Na dużym serwerze można to latami ignorować. Na małym VPS-ie za kilkanaście złotych prędzej czy później przychodzi dzień, w którym dysk jest pełny, a Ty się zastanawiasz, jak to możliwe, skoro przecież “prawie nic tam nie ma”.

Zanim cokolwiek usuniemy, zobaczmy skalę problemu:

docker system df

Dostaniesz rozbicie na obrazy, kontenery, wolumeny i cache buildera. Najciekawsza jest kolumna RECLAIMABLE, bo pokazuje, ile z tego możesz odzyskać bez żadnej szkody.

Szybkie posprzątanie wszystkiego naraz#

Pierwsza, najłagodniejsza opcja. Usuwa zatrzymane kontenery, sieci, z których nie korzysta żaden kontener, “wiszące” obrazy bez tagu i cache buildera:

docker system prune -f

-f (force) pomija pytanie o zgodę. W skryptach wygodne, ale pamiętaj, że komenda zrobi swoje bez mrugnięcia okiem. Jeśli chcesz najpierw zobaczyć listę ofiar, odpal bez -f.

Jest tylko jeden szkopuł. To podstawowe sprzątanie rusza jedynie obrazy pozbawione tagu (tzw. dangling). Pobrałeś kiedyś nginx:latest i dawno o nim zapomniałeś? Zwykłe docker system prune przejdzie obok niego obojętnie. Tu potrzeba cięższego kalibru, czyli -a:

docker system prune -a -f

Uwaga: z -a wylatują wszystkie obrazy, których nie używa żaden działający kontener. Włącznie z tymi, które ściągnąłeś specjalnie “na później”. Tragedii nie ma, bo przy następnym docker run czy docker compose up Docker pobierze je od nowa. Ale jeśli masz wolne łącze albo obrazy ważące po kilka gigabajtów, lepiej mieć to z tyłu głowy.

Sprzątanie punktowe#

Wolisz działać chirurgicznie? Możesz posprzątać tylko jedną kategorię.

Nieużywane obrazy:

docker image prune -a -f

Cache buildera. Przyrasta przy każdym docker build i potrafi po cichu dobić do kilku gigabajtów, zanim ktokolwiek się zorientuje:

docker builder prune -f

I nieużywane wolumeny:

docker volume prune -f

Z tym ostatnim naprawdę ostrożnie. Jeżeli w wolumenie trzymałeś dane usługi, która akurat stoi zatrzymana, ale wciąż jest Ci potrzebna, to po tej komendzie tych danych już nie ma. Ani w koszu, ani nigdzie indziej.

Automatyzacja przez cron#

Ręczne sprzątanie ma jedną zasadniczą wadę: trzeba o nim pamiętać. A kto pamięta? Dlatego lepiej zrzucić to na crona. Poniższy wpis czyści raz w tygodniu, w niedzielę o 4:00, i oszczędza wszystko, co powstało w ciągu ostatnich 7 dni:

sudo crontab -e
0 4 * * 0 /usr/bin/docker system prune -a -f --filter "until=168h" >> /var/log/docker-prune.log 2>&1

--filter "until=168h" (168 godzin, czyli tydzień) to taki bezpiecznik. Obrazy i cache z ostatniego tygodnia zostają nietknięte, więc cron nie skasuje Ci czegoś, co zbudowałeś wczoraj i za chwilę znowu będzie potrzebne.

Najczęstsze błędy#

"docker system prune nic nie sprzątnęło." Bez -a lecą wyłącznie obrazy bez tagu. Jeśli po prune docker system df nadal pokazuje sporo w RECLAIMABLE przy obrazach, sięgnij po wersję z -a.

Wyleciał wolumen z danymi, których jednak było szkoda. docker volume prune nie ma pojęcia, co jest dla Ciebie ważne. Usuwa każdy wolumen niepodpięty do żadnego kontenera, koniec kropka. Zanim go uruchomisz, przejrzyj docker volume ls i upewnij się, co jest czym.

Cache buildera rośnie, choć regularnie robisz system prune. docker system prune czyści cache, owszem, ale tylko te warstwy, z którymi nic już nie jest powiązane. Jeśli dużo budujesz, dorzuć osobno docker builder prune -f.