Назад в блог/df говорит 100%. Кто съел место — логи, Docker или journal?

df говорит 100%. Кто съел место — логи, Docker или journal?

Когда df показывает 100% на VPS: быстрый поиск виновника через du, journald, Docker prune и logrotate, плюс профилактика inode и алерты на 85%.

df говорит 100%. Кто съел место — логи, Docker или journal?

Когда df -h показывает корневой раздел на 100%, падают обновления, Docker, почта и даже SSH-сессии с записью. Это не то же самое, что «VPS тормозит из‑за iowait» — здесь проблема ёмкости. Ниже — быстрый поиск виновника: логи, journald, Docker, кэши и забытые дампы, плюс профилактика, чтобы диск снова не забился за неделю.

Диагностику CPU/диска по скорости мы разбирали в статье «VPS тормозит…». Сейчас — только место на диске. Бэкапы при забитом разделе тоже страдают: если нет куда писать дамп, проверка восстановления уже не спасёт — сначала освободите гигабайты.

Что ломается при 100%

Короткий список симптомов, по которым узнают «диск кончился», ещё до df:

  • apt upgrade падает с «No space left on device»;
  • Nginx/PHP пишут в error.log про невозможность создать временный файл;
  • Docker не стартует контейнеры, MySQL уходит в read-only;
  • cron-бэкап «успешен» в письме, а файл дампа нулевого размера;
  • journalctl сам перестаёт писать, и вы теряете следы инцидента.

Чем раньше поймаете порог 85–90%, тем меньше шанс чинить прод ночью. Дальше — пошаговый разбор.

Шаг 1. Где именно конец места

BASH
df -h
df -i

Смотрите и inode (df -i): раздел может быть «полным» при видимых свободных гигабайтах, если накопились миллионы мелких файлов (сессии PHP, кэш, mail queue, thumbnail’ы). Запишите, какой mount заполнен: /, /var, отдельный том под Docker — дальше du гоняйте именно по нему.

Пример чтения вывода:

  • /dev/sda1 на / — 100% → копаем корень;
  • отдельный /var/lib/docker — 98% → чистка Docker не поможет корню и наоборот;
  • Use% по inode 100%, по блокам 40% → ищем рой мелких файлов, а не «большой лог».

Схема: df 100% → du по каталогам → логи / journal / Docker
Поиск причины заполненного диска VPS

Быстрая сводка без лишнего шума:

BASH
df -hT | grep -v tmpfs
df -i | grep -v tmpfs

Шаг 2. Кто занимает каталоги

BASH
sudo du -xh / --max-depth=1 2>/dev/null | sort -h
sudo du -xh /var /home /usr /tmp --max-depth=1 2>/dev/null | sort -h

Частые «пожиратели» на VPS:

  • /var/log — access/error логи nginx, приложений;
  • /var/lib/docker — образы, volume, build cache;
  • /var/log/journal или systemd journal;
  • /var/lib/mysql / /var/lib/postgresql — данные БД (это уже не «почистить prune», а рост данных);
  • старые бэкапы и *.sql.gz в /root или /tmp;
  • /var/cache/apt после серии обновлений без autoclean.

Уточнение внутри /var:

BASH
sudo du -xh /var --max-depth=2 2>/dev/null | sort -h | tail -n 30

Флаг -x не уходит на другие файловые системы — удобно, если /var или Docker на отдельном диске. Без -x du может «уйти» на сетевой mount или bind и запутать картину.

Если подозреваете inode, а не гигабайты:

BASH
sudo find /var -xdev -type d -print0 2>/dev/null \
  | while IFS= read -r -d '' d; do
      echo "$(find "$d" -xdev -maxdepth 1 -type f 2>/dev/null | wc -l) $d"
    done | sort -n | tail -n 20

Грубо, но быстро показывает каталоги с кучей файлов на одном уровне (сессии, очереди, кэш картинок).

Шаг 3. journald

BASH
journalctl --disk-usage
sudo journalctl --vacuum-size=200M
# или
sudo journalctl --vacuum-time=7d

Ограничьте рост постоянно в /etc/systemd/journald.conf (раскомментируйте и задайте):

INI
[Journal]
SystemMaxUse=200M
SystemKeepFree=500M
MaxRetentionSec=14day

Затем:

BASH
sudo systemctl restart systemd-journald
journalctl --disk-usage

Для расследования инцидента сначала сохраните нужный кусок, потом уже vacuum:

BASH
journalctl --since '2026-09-20' --until '2026-09-21' > /root/incident.log
# только после копирования:
sudo journalctl --vacuum-size=200M

Не кладите incident.log обратно в /var/log без ротации — иначе через неделю сами себе устроите повтор. После разбора перенесите файл на бэкап-хост или удалите.

Шаг 4. Docker без жалости к кэшу — но с головой

BASH
docker system df
docker system prune -a --volumes

--volumes удалит неиспользуемые volume — убедитесь, что там нет нужных данных. Часто после серии CI/CD на VPS остаются десятки гигабайт висячих образов и build cache.

Более осторожный порядок:

BASH
docker builder prune -f
docker image prune -a -f
docker container prune -f
docker volume ls
# volumes — только после проверки, что том не нужен:
# docker volume prune -f

Перед агрессивной очисткой имеет смысл глянуть, что занимает место внутри Docker:

BASH
docker system df -v | head -n 80
sudo du -xh /var/lib/docker --max-depth=1 2>/dev/null | sort -h

Если Docker лежит на отдельном томе, смотрите df -h именно по этому mount — очистка / не поможет. И наоборот: полный корень при пустом томе Docker лечится логами и journal, а не prune.

Отдельная ловушка — build на проде. Если CI собирает образы прямо на боевом VPS, заведите лимит и регулярный docker builder prune. Лучше собирать на отдельной машине и пушить в registry.

Шаг 5. Логи приложений и logrotate

Nginx/Apache access-логи на загруженном сайте раздуваются за дни. Включите logrotate, проверьте /etc/logrotate.d/. Временная мера на горящем диске:

BASH
sudo truncate -s 0 /var/log/nginx/access.log
sudo truncate -s 0 /var/log/nginx/error.log

truncate обнуляет файл, не меняя inode — процесс, который держит лог открытым, продолжает писать в тот же файл, и место освобождается сразу. Это лучше, чем rm: после rm процесс может продолжать писать в удалённый inode, и df не отпустит гигабайты, пока сервис не перезапустите.

Проверка «удалён, но открыт»:

BASH
sudo lsof +L1 2>/dev/null | head
# или
sudo lsof 2>/dev/null | grep deleted | head

Лучше ротация, чем ручной truncate на постоянке. Пример фрагмента для nginx (обычно уже есть пакетный файл — проверьте, что он не отключён):

BASH
sudo cat /etc/logrotate.d/nginx
sudo logrotate -d /etc/logrotate.d/nginx   # dry-run
sudo logrotate -f /etc/logrotate.d/nginx   # принудительно

Для приложений в /var/www и PM2/systemd проверьте собственные log-файлы: иногда ротируется только nginx, а Node/PHP пишет гигабайты рядом (storage/logs, .pm2/logs, ~/.npm/_logs). Для systemd unit можно ограничить размер через StandardOutput=append:... и внешний rotate или журналировать в journald с лимитом из шага 3.

Apt-кэш после обновлений:

BASH
sudo apt-get clean
sudo apt-get autoclean
du -sh /var/cache/apt

Шаг 6. Большие файлы точечно

BASH
sudo find /var -xdev -type f -size +200M -printf '%s %p\n' 2>/dev/null | sort -n | tail
sudo find /root /tmp /home -xdev -type f -size +100M -printf '%s %p\n' 2>/dev/null | sort -n | tail

Ищите забытые дампы БД, ядра (core), старые node_modules в /tmp, архивы деплоя, *.sql.gz месячной давности. Перед удалением убедитесь, что файл не нужен для отката — и что копия уже есть на другом носителе.

Подозрительные имена:

  • /root/backup.sql, /tmp/dump.sql.gz;
  • core, core.* в домашних и /var/crash;
  • старые релизы в /var/www/releases без очистки;
  • *.tar.gz деплоя по 500M+ в /home.

Если нашли огромный дамп и он единственный — сначала скопируйте на бэкап-хост, потом удаляйте с прода. Иначе «освободили диск» ценой потери единственной копии.

Профилактика

  • алерт на df > 85% (и отдельно на inode > 85%);
  • logrotate для веб и приложений, проверка раз в квартал;
  • лимит journald в journald.conf;
  • периодический docker system df в cron с письмом, если reclaimable > N гигабайт;
  • бэкапы — на другой диск/хост (см. статью про бэкапы и проверку восстановления);
  • не собирать Docker-образы на том же маленьком проде без ротации кэша.

Простейший cron-мониторинг места:

BASH
#!/bin/bash
# /usr/local/bin/check-disk.sh
THRESH=85
USE=$(df -P / | awk 'NR==2 {gsub(/%/,""); print $5}')
if [ "$USE" -ge "$THRESH" ]; then
  echo "Disk / at ${USE}% on $(hostname)" | mail -s "VPS disk alert" you@example.com
  # или curl в Telegram bot API
fi
CRON
0 * * * * /usr/local/bin/check-disk.sh

Если раздел систематически мал под ваши данные и логи, сравните тарифы с большим NVMe на azerta.ru/vps/nvme или общий каталог VPS. Выдача до 120 секунд после оплаты; для временного «увеличить и переехать» удобна посуточная оплата на время миграции.

Связка с «тормозами»

Забитый диск часто маскируется под медленный сайт: растёт iowait, пишутся ошибки БД, перестают ротироваться логи. Сначала освободите место и убедитесь, что сервисы снова пишут на диск, затем уже гоняйте чек-лист из статьи про диагностику тормозов VPS.

Отдельно проверьте, не включился ли read-only режим из‑за ошибок ФС:

BASH
mount | grep ' / '
dmesg -T | grep -i -E 'readonly|i/o error|ext4' | tail

Если после очистки снова упираетесь в объём за недели — это сигнал увеличить диск или вынести логи/бэкапы наружу, а не бесконечно делать prune. Prune лечит симптом накопленного мусора; рост media-библиотеки и БД лечится ёмкостью и архитектурой хранения.

Чек-лист за 20 минут

  1. df -h и df -i — какой mount и чего не хватает (блоки или inode).
  2. du -xh / --max-depth=1 — верхний уровень виновников.
  3. journal vacuum + лимит в journald.conf.
  4. docker system df → осмысленный prune (volumes — только осознанно).
  5. logrotate / truncate больших access-логов; проверить lsof на deleted.
  6. find по файлам >200M, удалить только осознанно.
  7. Алерт на 85% и план: куда растут данные дальше (БД, media, логи, Docker).

FAQ

Почему df полный, а du меньше? Удалённые, но открытые файлы; или другой mount point. Смотрите sudo lsof +L1 / lsof | grep deleted и отдельно каждый mount. Ещё вариант — файлы в bind-mount или под overlay, куда du без -x зашёл иначе, чем вы ожидали.

Безопасно ли vacuum journal? Да, вы теряете старые логи. Для расследования инцидентов сначала скопируйте нужный кусок на другой диск. Лимит в journald.conf безопаснее регулярного ручного vacuum «на глаз».

Docker prune удалит контейнеры? docker container prune удаляет только остановленные. docker system prune -a снимет неиспользуемые образы — работающие контейнеры останутся, но «лишние» теги уйдут. --volumes опаснее: читайте вывод docker volume ls и документацию до ввода -f.

Закончились inode — что делать? Ищите каталоги с миллионами мелких файлов (кэши, сессии, mail queue) через подсчёт файлов, чистите или выносите на другой раздел. Увеличение диска по блокам без смены ФС inode само не добавит магически — иногда нужен новый раздел с другими параметрами или другая схема хранения сессий (Redis вместо файлов).

Можно ли расширить диск без переезда? Зависит от панели и типа диска. Часто проще заказать больший NVMe и перенести данные по плану миграции, чем жить на вечном prune. Сверьте NVMe VPS и обычный каталог под ваш объём данных и логов.

Нужно ли трогать данные MySQL/PostgreSQL при 100%? Не удаляйте «старые таблицы на глаз». Сначала логи, journal, Docker, дампы в /tmp. Рост БД — отдельная задача: архивация, партиции, вынос cold-данных, увеличение диска.

Документация

Нужен быстрый сервер под ваш проект?

Арендуйте производительный KVM VPS в Москве или Германии на скоростных NVMe дисках от 300 ₽/мес. Автовыдача за 60 секунд, выделенный IPv4 и защита от DDoS.

Выбрать тариф