Cleanup checklist
Безопасное освобождение места. Категории, предварительный просмотр, что удаляется безвозвратно.
Ни одну команду
pruneне следует запускать, не посмотрев сначала, что именно она удалит. Полминуты на просмотр дешевле потерянного тома.
Порядок
Всегда снизу вверх по опасности: сначала то, что восстанавливается само, потом то, что не восстанавливается никак.
| Шаг | Что | Восстановимо |
|---|---|---|
| 1 | Кэш сборки | Да, пересборкой |
| 2 | Остановленные container'ы | Да, пересозданием |
| 3 | Логи container'ов | Нет, но обычно не нужны |
| 4 | Безымянные образы | Да, пересборкой |
| 5 | Неиспользуемые образы | Да, загрузкой из registry |
| 6 | Тома | Нет. Это данные |
0. Сначала посмотреть
# -v печатает подробные разделы; общая сводка — без него
docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 47 8 18.2GB 14.1GB (77%)
Containers 12 5 340MB 120MB (35%)
Local Volumes 9 4 6.8GB 2.1GB (30%)
Build Cache 231 0 9.4GB 9.4GB
Разбивку по образам, container'ам и томам даёт docker system df -v — вывод длинный, начинается с раздела Images space usage:.
Логи container'ов в этот вывод не входят. Проверять отдельно:
du -sh /var/lib/docker/containers/*/*-json.log 2>/dev/null | sort -h | tail -5
Это самая частая причина заполнения диска и та, которую ищут дольше всего.
1. Кэш сборки
# Посмотреть
docker builder du
# Удалить неиспользуемое
docker builder prune
# Удалить старше недели
docker builder prune --filter 'until=168h'
# Удалить всё
docker builder prune -a
☐ Проверено, что нет сборки в процессе
Безопасно. Восстанавливается пересборкой; цена — время следующей сборки.
2. Остановленные container'ы
# Посмотреть
docker ps -a --filter status=exited --format 'table {{.Names}}\t{{.Status}}\t{{.Size}}'
# Удалить
docker container prune
# Удалить старше суток
docker container prune --filter 'until=24h'
☐ Среди них нет тех, чьи логи ещё понадобятся
Что теряется: логи и записываемый слой удаляемых container'ов. Если расследование не закончено — сначала сохранить:
docker logs ИМЯ > /tmp/ИМЯ.log 2>&1
3. Логи container'ов
# Посмотреть, у кого самые большие
du -sh /var/lib/docker/containers/*/*-json.log | sort -h | tail -5
# Сопоставить каталог с именем
for d in /var/lib/docker/containers/*/; do
id=$(basename "$d")
name=$(docker inspect "$id" --format '{{.Name}}' 2>/dev/null)
size=$(du -sh "$d"/*-json.log 2>/dev/null | cut -f1)
[ -n "$size" ] && printf '%-8s %s\n' "$size" "$name"
done | sort -h | tail -5
Очистить лог работающего container'а без перезапуска:
sudo truncate -s 0 /var/lib/docker/containers/ID/ID-json.log
☐ Настроена ротация, чтобы не повторилось
logging:
driver: json-file
options: {max-size: "10m", max-file: "3"}
Или для всех container'ов сразу — в /etc/docker/daemon.json:
{
"log-driver": "json-file",
"log-opts": {"max-size": "10m", "max-file": "3"}
}
Ротация не включена по умолчанию. Без неё лог растёт неограниченно — и это не ошибка настройки, а поведение по умолчанию.
4. Безымянные образы
# Посмотреть
docker images -f dangling=true
# Удалить
docker image prune
☐ Проверено, что среди них нет промежуточных стадий текущей сборки
Откуда берутся. Сборка с тем же тегом переносит тег на новый образ; старый остаётся без имени. Один docker build в день — тридцать безымянных образов в месяц.
Чтобы не возникали: неизменяемые теги по SHA коммита вместо перезаписываемых.
5. Неиспользуемые образы
# Посмотреть, что удалится
docker images --format 'table {{.Repository}}:{{.Tag}}\t{{.Size}}\t{{.CreatedSince}}'
# Кто используется прямо сейчас
docker ps -a --format '{{.Image}}' | sort -u
# Удалить старше недели
docker image prune -a --filter 'until=168h'
☐ Образы, на которые может понадобиться откат, сохранены
☐ Список используемых сверен
Опасно в эксплуатации. docker image prune -a удаляет образы, не привязанные к работающим container'ам, — в том числе предыдущую версию, на которую вы собирались откатываться.
Безопаснее — точечно:
docker rmi образ:конкретный-тег
6. Тома
# Посмотреть неиспользуемые
docker volume ls -f dangling=true
# Заглянуть внутрь ДО удаления
for v in $(docker volume ls -f dangling=true -q); do
echo "── $v"
docker run --rm -v "$v:/data:ro" alpine sh -c 'du -sh /data; ls /data | head -5'
done
☐ Содержимое каждого просмотрено
☐ Резервная копия сделана, если данные ценны
☐ Проверено, что том не принадлежит остановленному стеку
docker volume prune # только неиспользуемые
docker volume rm имя # точечно
Удаляется безвозвратно. Единственная категория в этом списке, где ошибка необратима.
Частая ловушка: docker compose down -v удаляет тома проекта. Без -v — не удаляет. Разница в две буквы и в наличии данных.
Что не делать в эксплуатации
| Команда | Почему |
|---|---|
docker system prune -a | Удаляет образы для отката |
docker volume prune без просмотра | Удаляет данные |
docker rm -f $(docker ps -aq) | Убивает работающие сервисы |
rm -rf /var/lib/docker | Удаляет всё; демон нужно перезапускать |
Профилактика
Место кончается предсказуемо. Четыре настройки, устраняющие большую часть причин:
| Настройка | Где | Что предотвращает |
|---|---|---|
| Ротация логов | daemon.json или compose.yaml | Рост логов |
| Неизменяемые теги | Конвейер сборки | Безымянные образы |
Регулярный builder prune | Задание по расписанию | Рост кэша сборки |
| Мониторинг места | Наблюдение за узлом | Внезапность |
# Еженедельная очистка безопасного
docker builder prune -f --filter 'until=168h'
docker image prune -f
docker container prune -f --filter 'until=168h'
Тома в этот список не входят намеренно: их очистка не автоматизируется.
Быстрая проверка после очистки
docker system df
df -h /var/lib/docker
docker ps --format 'table {{.Names}}\t{{.Status}}'
Третья команда важнее первых двух: убедиться, что очистка ничего не сломала.
Навигация
Вернуться к справочникам
Storage cheat sheet
Debugging checklist
Урок 13.4. Место на диске
Главное оглавление