Короткий ответ
Чистка — по карте docker system df, не одной «магической» командой. Порядок: логи json-file, dangling images, build cache, точечный docker image rm старых тегов. Исключены: volume app_data, образы текущего и прошлого релиза. docker system prune -a и тем более docker system prune -a --volumes на проде проекта app запрещены без явного списка жертв и бэкапа.
Симптомы и как отличить
- Нужно место, стек должен выжить;
- уже кто-то запустил
-a,compose pullкачает часами; volume lsне показываетapp_data;- путают builder cache и volumes в du.
| Команда | Образы tagged unused | Dangling | Volumes |
|---|---|---|---|
image prune | нет | да | нет |
image prune -a | да | да | нет |
system prune | нет | да + stopped containers + net | нет |
system prune -a --volumes | да | да | неиспользуемые тома |
Возможные причины
- json.log — тогда не prune, ротация.
- CI образы — dangling.
- builder на том же хосте, что прод.
- Реальный рост
app_data— чистка Docker не поможет, нужны данные/диск. - Привычка cron
-a.
Диагностика
df -h /var/lib/docker
docker system df
docker system df -v | head -n 60
docker compose -f /opt/app/compose.yaml ps -a
docker volume ls
docker volume inspect app_data --format '{{.Name}} inuse-check via ps'Список «священных» тегов:
docker compose images
docker images | grep 'registry.example:5000/app'Stopped контейнеры:
docker ps -a --filter status=exitedsystem prune удалит exited контейнеры, не тома (без --volumes). Обычно ок, если это не контейнер с анонимным volume, который вы ещё не переименовали.
Решение
Сценарий A. Безопасный минимум
docker image prune
docker builder prune --filter until=168hПеречитайте system df. Часто этого хватает вместе с ротацией логов.
Сценарий B. Старые теги вручную
docker image rm registry.example:5000/app/web:1.0.9Оставьте текущий и N-1.
Сценарий C. Exited мусор
docker container pruneНе трогает running. Проверьте, что не удаляете контейнер с уникальным анонимным томом без бэкапа.
Сценарий D. Когда volume prune допустим
Только после docker volume ls и явного allowlist. На хосте только app — не запускайте volume prune. Если лабораторный хост:
docker volume ls
# удалить по имени мусорный том:
docker volume rm old_tmp_volumeНе prune оптом.
Сценарий E. Уже сделали prune -a --volumes
- Не пишите на диск поверх.
- Ищите
/var/backups, снапшоты СХД, object storage. - Registry ещё может отдать образы, данные тома — нет.
- Дальше IR, не повторный prune.
Cron docker system prune -af --volumes встречается в gist «очистка сервера». На host.example с остановленным на ночь app это удалит app_data как unused. Запретите -f в cron: интерактивное подтверждение хотя бы раз учит читать список. Для автоматизации — явные docker image rm по allowlist тегов старше N, никогда --volumes.
container prune удалит Exited migrate-контейнеры, это обычно ок. Не удалит running. Сети: unused app_default после down prune сети безвреден, up создаст снова. Образы tagged unused — ценность отката; их не отдавайте оптом.
Build cache на прод-хосте — сначала организационный долг. builder prune --filter until=168h безопаснее --all, который снесёт кэш сегодняшней ночной сборки, если вы всё ещё собираете здесь. После prune проверьте compose ps и volume inspect app_data.
Запись в журнал изменений: что удалили, сколько места, кто. Иначе через неделю «пропал образ отката» без следа. Связка с dangling и логами: чистите класс объектов, который показал du, не все классы сразу.
Как проверить, что проблема устранена
df -h /var/lib/docker
docker system df
docker compose -f /opt/app/compose.yaml ps
docker volume inspect app_data >/dev/null && echo app_data_ok
docker compose exec web ls /var/lib/app | headСтек Running, том на месте, место освободилось за счёт images/cache/logs, не за счёт данных. Rollback-образ ещё docker images.
Если не помогло
- df не упал: логи или
app_dataили deleted-open. - Стек не стартует: pull с registry.
volume is in useпри rm — и правильно, не-fборьба.- BuildKit cache в другом
DOCKER_BUILDKITroot.
Не используйте docker volume prune --filter label!=keep пока не разметите метки на app_data. Без меток фильтр всё равно опасен. На проде только явный volume ls и точечный rm чужого мусора. Перед rm — inspect и бэкап, если имя не очевидно тестовое. После чистки сравните df и compose ps, чтобы не принять удаление данных за успех.
Профилактика
- Документ: разрешённые команды vs запрет
-a/--volumes. - CI runner ≠ prod volume data.
- Алерт df 80%.
- Ротация логов глобально.
- Имена томов явные
app_data.
После любой чистки пройдите compose ps, health, df. Если освободилось меньше ожидания — вы чистили не тот класс (логи vs images). Не добавляйте сразу -a. Запишите в тикет список docker images до/после.
FAQ
system prune без флагов на проде?
Относительно мягкий: dangling + stopped containers + unused networks. Не трогает tagged images и volumes. Всё равно посмотрите ps -a до.
--filter until
Полезен для dangling/build. Не заменяет запрет -a.
Почему unused network удалять ок?
Да, app_default живой сети running стека prune не удалит. После down сеть может уйти — up создаст снова. Данных нет.
container prune vs compose rm
Смотрите имена app-*. Не чистите чужой стек на том же Engine.
Можно ли cron image prune?
Да, без -a, после часов. Не volume prune.