Обслуживание Docker хоста

TL;DR: docker system prune — быстрая очистка. docker system df — анализ. Без ротации логов Docker заполнит диск. Автоматизируй через cron.

Со временем Docker хост накапливает “мусор”: остановленные контейнеры, старые версии образов, неиспользуемые тома и гигабайты логов. Без регулярного обслуживания это приведет к ошибке No space left on device.

1. Очистка диска (Garbage Collection)

Docker имеет встроенные команды для очистки (prune).

Безопасная очистка

Удаляет ресурсы, которые точно не нужны (остановленные контейнеры, dangling images, неиспользуемые сети).

docker system prune

Вам предложат подтвердить действие. Для автоматизации добавьте флаг -f (force).

Полная очистка (Deep Clean)

Удаляет вообще все образы, которые не используются ни одним запущенным контейнером.

Внимание: Это удалит кэш сборки и базовые образы (ubuntu, alpine), если они сейчас не запущены. Следующий docker run будет заново качать их из интернета.

docker system prune -a --volumes
  • -a: Удалить все неиспользуемые образы (а не только dangling).
  • --volumes: Удалить неиспользуемые тома (очень опасно для БД, если вы случайно остановили контейнер с базой!).

Выборочная очистка

Если вы боитесь делать system prune, чистите по категориям:

# Удалить образы <none> (dangling), которые образовались после docker build
docker image prune
 
# Удалить тома, не привязанные к контейнерам
docker volume prune
 
# Удалить кэш сборщика (освобождает много места!)
docker builder prune

2. Анализ занимаемого места

Чтобы понять, кто съел диск:

docker system df

Детальный разбор (какой именно образ сколько занимает):

docker system df -v

3. Управление логами

По умолчанию Docker использует драйвер json-file и не ограничивает размер логов. Один контейнер может забить весь диск за сутки.

Решение 1: Глобальная настройка (Рекомендуется)

Настройте ротацию для всех новых контейнеров в /etc/docker/daemon.json:

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

После изменения нужно перезапустить докер (systemctl restart docker) и пересоздать существующие контейнеры.

Решение 2: Настройка в Compose (Локально)

Если у вас нет доступа к конфигу демона, настройте в compose.yaml:

services:
  app:
    image: my-app
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

Как очистить логи без рестарта?

Иногда нужно срочно освободить место, не останавливая прод-контейнер. Просто удалить файл JSON нельзя (процесс держит дескриптор, место не освободится). Нужно “обнулить” файл (truncate):

# Найти путь к лог-файлу
LOG_PATH=$(docker inspect --format='{{.LogPath}}' <container_name>)
 
# Обнулить файл
truncate -s 0 $LOG_PATH

4. Автоматизация (Cron)

На продакшн серверах полезно настроить еженедельную очистку.

Добавьте в crontab -e:

# Каждое воскресенье в 03:00 чистить dangling images и кэш билдера
0 3 * * 0 /usr/bin/docker image prune -f && /usr/bin/docker builder prune -f

(Не используйте system prune -a в кроне, если не уверены на 100%, что это безопасно для вашего workflow).

Типичные ошибки

ОшибкаСимптомРешение
docker system prune -a на продеУдалил все образы, включая рабочиеБез -a — удаляются только dangling. С -a — все неиспользуемые
Не настроена ротация логов/var/lib/docker/containers/ заполнил дискdaemon.json: max-size: 10m, max-file: 3
docker volume prune без проверкиУдалил данные БДВсегда проверяй docker volume ls перед prune
Забыли про build cachedocker system df показывает 50GB cachedocker builder prune — отдельная команда для кэша