Главная/Справочники/Справочник

Cleanup checklist

Безопасное освобождение места. Категории, предварительный просмотр, что удаляется безвозвратно.

Ни одну команду prune не следует запускать, не посмотрев сначала, что именно она удалит. Полминуты на просмотр дешевле потерянного тома.

Порядок

Всегда снизу вверх по опасности: сначала то, что восстанавливается само, потом то, что не восстанавливается никак.

ШагЧтоВосстановимо
1Кэш сборкиДа, пересборкой
2Остановленные container'ыДа, пересозданием
3Логи container'овНет, но обычно не нужны
4Безымянные образыДа, пересборкой
5Неиспользуемые образыДа, загрузкой из registry
6ТомаНет. Это данные

0. Сначала посмотреть

bash
# -v печатает подробные разделы; общая сводка — без него
docker system df
text
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'ов в этот вывод не входят. Проверять отдельно:

bash
du -sh /var/lib/docker/containers/*/*-json.log 2>/dev/null | sort -h | tail -5

Это самая частая причина заполнения диска и та, которую ищут дольше всего.


1. Кэш сборки

bash
# Посмотреть
docker builder du

# Удалить неиспользуемое
docker builder prune

# Удалить старше недели
docker builder prune --filter 'until=168h'

# Удалить всё
docker builder prune -a

☐ Проверено, что нет сборки в процессе

Безопасно. Восстанавливается пересборкой; цена — время следующей сборки.


2. Остановленные container'ы

bash
# Посмотреть
docker ps -a --filter status=exited --format 'table {{.Names}}\t{{.Status}}\t{{.Size}}'

# Удалить
docker container prune

# Удалить старше суток
docker container prune --filter 'until=24h'

☐ Среди них нет тех, чьи логи ещё понадобятся

Что теряется: логи и записываемый слой удаляемых container'ов. Если расследование не закончено — сначала сохранить:

bash
docker logs ИМЯ > /tmp/ИМЯ.log 2>&1

3. Логи container'ов

bash
# Посмотреть, у кого самые большие
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'а без перезапуска:

bash
sudo truncate -s 0 /var/lib/docker/containers/ID/ID-json.log

☐ Настроена ротация, чтобы не повторилось

yaml
logging:
  driver: json-file
  options: {max-size: "10m", max-file: "3"}

Или для всех container'ов сразу — в /etc/docker/daemon.json:

json
{
  "log-driver": "json-file",
  "log-opts": {"max-size": "10m", "max-file": "3"}
}

Ротация не включена по умолчанию. Без неё лог растёт неограниченно — и это не ошибка настройки, а поведение по умолчанию.


4. Безымянные образы

bash
# Посмотреть
docker images -f dangling=true

# Удалить
docker image prune

☐ Проверено, что среди них нет промежуточных стадий текущей сборки

Откуда берутся. Сборка с тем же тегом переносит тег на новый образ; старый остаётся без имени. Один docker build в день — тридцать безымянных образов в месяц.

Чтобы не возникали: неизменяемые теги по SHA коммита вместо перезаписываемых.


5. Неиспользуемые образы

bash
# Посмотреть, что удалится
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'ам, — в том числе предыдущую версию, на которую вы собирались откатываться.

Безопаснее — точечно:

bash
docker rmi образ:конкретный-тег

6. Тома

bash
# Посмотреть неиспользуемые
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

☐ Содержимое каждого просмотрено
☐ Резервная копия сделана, если данные ценны
☐ Проверено, что том не принадлежит остановленному стеку

bash
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Задание по расписаниюРост кэша сборки
Мониторинг местаНаблюдение за узломВнезапность
bash
# Еженедельная очистка безопасного
docker builder prune -f --filter 'until=168h'
docker image prune -f
docker container prune -f --filter 'until=168h'

Тома в этот список не входят намеренно: их очистка не автоматизируется.


Быстрая проверка после очистки

bash
docker system df
df -h /var/lib/docker
docker ps --format 'table {{.Names}}\t{{.Status}}'

Третья команда важнее первых двух: убедиться, что очистка ничего не сломала.


Навигация

Вернуться к справочникам
Storage cheat sheet
Debugging checklist
Урок 13.4. Место на диске
Главное оглавление

Markdown на GitHub ↗