Выберите продукт

Debian/Ubuntu: как исправить overlayfs: no space left on device в Docker и containerd

Ошибка overlayfs: no space left on device в Docker и containerd не всегда означает, что на сервере закончились гигабайты. На Debian и Ubuntu причина часто связана с inode, логами, build cache, overlay2 и deleted-файлами. Ниже — пошаговая диагностика, безопасная очистка и профилактика.
Debian/Ubuntu: как исправить overlayfs: no space left on device в Docker и containerd

Ошибка overlayfs: no space left on device в Docker или containerd почти всегда появляется не вовремя: контейнер перестаёт стартовать, сборка образа падает, CI ломается, а внутри приложения начинают сыпаться ENOSPC. При этом обычная проверка через df -h нередко показывает, что свободное место как будто ещё есть.

Подвох в том, что для контейнерных рантаймов «место закончилось» означает не только нехватку байтов на файловой системе. Причиной могут быть исчерпанные inode, переполненные логи, разросшийся build cache, старые слои overlay2, неочищенные snapshot-ы containerd и удалённые, но всё ещё открытые файлы.

Ниже — практический runbook для Debian и Ubuntu: как быстро локализовать проблему, безопасно очистить мусор и не сломать рабочие контейнеры по пути.

Первое правило диагностики: всегда проверяйте и объём диска, и inode. Связка df -h и df -i почти всегда даёт верную картину быстрее, чем хаотичная очистка.

Что означает ошибка и откуда она берётся

Сообщения могут выглядеть так:

overlayfs: no space left on device
write /var/lib/docker/...: no space left on device
failed to extract layer: no space left on device
containerd: failed to write: no space left on device

На практике чаще всего встречаются четыре причины:

  • закончились байты на разделе, где лежит /var/lib/docker или /var/lib/containerd;
  • закончились inode, и файловая система больше не может создавать новые файлы;
  • накопились неиспользуемые образы, слои, stopped-контейнеры, cache и тома;
  • место удерживают уже удалённые, но открытые файлы, чаще всего логи.

Для Docker это особенно характерно при активной работе со слоями overlay2. Частые сборки, BuildKit, короткоживущие контейнеры и постоянные деплои очень быстро раздувают дерево в /var/lib/docker/overlay2. Даже если суммарный размер образов выглядит умеренным, количество мелких файлов может быть огромным.

У containerd ситуация похожая: content store, snapshot-ы и служебные данные обычно лежат в /var/lib/containerd. Если на узле работает Kubernetes, k3s или другой стек поверх containerd, рост каталога идёт не менее активно.

Сначала диагностика: где именно кончилось место

Самая частая ошибка в инциденте — сразу запускать агрессивный prune. На прод-сервере это может освободить место, но одновременно удалить полезный кэш, образы для отката или данные, которые ещё нужны.

Проверяем объём диска и inode

df -h
df -i

Смотрите прежде всего на разделы с /var, /var/lib/docker, /var/lib/containerd и /tmp. Если в df -h раздел близок к 100%, проблема в байтах. Если 100% показывает df -i, у вас типичный случай исчерпания inode.

Очень распространённый сценарий: по объёму занято только 50–60%, но inode уже кончились. Для overlayfs это выглядит ровно как обычный disk full.

Смотрим, кто занял место в /var

du -xh /var --max-depth=1 | sort -h
du -xh /var/lib --max-depth=1 | sort -h
du -xh /var/lib/docker --max-depth=1 | sort -h
du -xh /var/lib/containerd --max-depth=2 | sort -h | tail -n 30

Так можно быстро понять, виноват ли действительно Docker или containerd, либо место забрали journald, apt-кэш, временные файлы или логи приложений.

Для Docker смотрим сводку рантайма

docker system df
docker ps -a
docker images
docker volume ls

Команда docker system df особенно полезна тем, что показывает отдельно образы, контейнеры, локальные тома и build cache. Это помогает не чистить вслепую.

Для containerd проверяем snapshot-ы и content store

ctr -n k8s.io containers ls
ctr -n k8s.io images ls
ctr -n k8s.io snapshots ls
ctr -n k8s.io content ls

Если у вас используется не k8s.io, а другой namespace, подставьте его явно. Это частая причина путаницы, когда кажется, что в containerd почти пусто, а место продолжает исчезать.

Ищем удалённые, но занятые файлы

lsof +L1 | sort -k7 -n

Если процесс держит большой уже удалённый файл, du его не покажет, но место не освободится. Особенно часто это происходит с логами контейнеров и приложений после неудачной ротации.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Если у вас контейнеры крутятся на небольшом сервере и каталог /var/lib/docker стабильно растёт, иногда проще заранее вынести такую нагрузку на отдельный VDS с нормальным запасом по диску, чем регулярно тушить аварии на переполненном системном разделе.

Проверка диска и inode на сервере перед очисткой Docker и containerd

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

Если виноват именно Docker, идите от самого безопасного варианта к более агрессивному. Ручное удаление каталогов внутри /var/lib/docker почти всегда плохая идея.

Удаляем stopped-контейнеры, dangling-образы и неиспользуемые сети

docker system prune
docker system prune -f

Это базовая и сравнительно безопасная очистка. Она не удаляет используемые тома и образы, но часто уже освобождает заметный объём.

Чистим build cache

docker builder prune
docker builder prune -a

На build-хостах именно кэш сборки часто оказывается главным потребителем места. Ключ -a удаляет весь неиспользуемый кэш, а не только dangling-слои.

Удаляем неиспользуемые образы

docker image prune -a

Эта команда агрессивнее: она удаляет все образы, не привязанные к работающим контейнерам. Если вы рассчитываете на локальный быстрый rollback, сначала проверьте, что именно удаляете.

Осторожно с томами

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

docker volume ls
docker volume prune

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

Самая дорогая по последствиям ошибка при аварийной очистке — удалить volumes в надежде быстро освободить место. Инцидент с диском пройдёт, но может начаться уже инцидент с потерей данных.

Проверяем логи контейнеров

Если используется драйвер json-file, логи в /var/lib/docker/containers могут занимать десятки гигабайт.

du -xh /var/lib/docker/containers --max-depth=2 | sort -h | tail -n 30

Для аварийного освобождения места можно обнулить крупные лог-файлы:

find /var/lib/docker/containers -name '*-json.log' -type f -size +100M -exec truncate -s 0 {} ;

После этого обязательно настройте ротацию, иначе проблема вернётся. Пример /etc/docker/daemon.json:

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

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

Что делать, если раздулся overlay2

Если основной объём сидит в /var/lib/docker/overlay2, почти всегда речь о слоях образов, writable-слоях старых контейнеров или build cache. Удалять каталоги внутри overlay2 вручную нельзя: так легко повредить состояние Docker.

  1. Проверьте, какие контейнеры реально работают.
  2. Сверьте цифры через docker system df.
  3. Запустите docker system prune.
  4. При необходимости очистите кэш через docker builder prune -a.
  5. Удалите ненужные образы через docker image prune -a.
  6. Проверьте deleted-файлы через lsof +L1.

Если место в overlay2 растёт постоянно, пересмотрите политику сборок и хранения локальных image. На CI-хостах полезно также ограничить накопление промежуточных артефактов. Если в вашей инфраструктуре много обратных прокси и кэша, пригодится и отдельная оптимизация дисковых данных, например через разбор кэширования Redis и Memcached для PHP.

Иногда правильное решение — вынести data-root Docker на отдельный раздел большего объёма:

systemctl stop docker
rsync -aHAXx /var/lib/docker/ /srv/docker/
mkdir -p /etc/docker
{
  "data-root": "/srv/docker"
}
mv /var/lib/docker /var/lib/docker.bak
systemctl start docker

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

Виртуальный хостинг FastFox
Виртуальный хостинг для сайтов
Универсальное решение для создания и размещения сайтов любой сложности в Интернете от 95₽ / мес

Очистка containerd без ручной порчи snapshot store

С containerd нужно быть аккуратнее, особенно на Kubernetes-узлах. Самое плохое решение — удалять файлы прямо внутри служебных каталогов без понимания, кто и как их использует.

Смотрим, что занимает место

du -xh /var/lib/containerd --max-depth=2 | sort -h | tail -n 50

Обычно основной объём сидит в каталогах io.containerd.snapshotter.v1.overlayfs и io.containerd.content.v1.content.

Если используется nerdctl

nerdctl system df
nerdctl image prune -a
nerdctl container prune
nerdctl volume prune

Для standalone-сценариев это самый удобный путь: логика похожа на Docker, но не забывайте учитывать namespace.

Если это Kubernetes-узел

На Kubernetes лучше использовать инструменты уровня CRI и kubelet:

crictl images
crictl ps -a
crictl rmi --prune

Если узел уже испытывает disk pressure, проблема может быть не только в containerd, но и в общей нехватке места под логи, временные файлы и образы. В этом случае полезно проверять не только runtime, но и системные компоненты, включая настройку логов и кэшей веб-стека, если на узле есть фронтенд-сервисы. Для Nginx-площадок рядом по теме может быть полезен разбор кэширования subrequest и SSI в Nginx.

Ручное удаление каталогов внутри /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs допустимо только как крайняя мера, после остановки зависимых сервисов и с полным пониманием последствий.

Очистка хранилища Docker и containerd на Linux-сервере

Когда виноваты не байты, а inode

Если df -i показывает 100%, то удаление одного большого файла почти не поможет. Нужно сокращать количество файлов, а не только их размер.

Типичные источники исчерпания inode:

  • слои образов и build cache;
  • разросшиеся каталоги логов;
  • временные директории CI;
  • артефакты сборки вроде node_modules, vendor и package cache;
  • контейнерные данные с огромным числом мелких файлов.

Быстро оценить масштаб можно так:

find /var/lib/docker -xdev -printf '.' | wc -c
find /var/lib/containerd -xdev -printf '.' | wc -c
find /var/log -xdev -printf '.' | wc -c

Если inode регулярно заканчиваются именно на контейнерных хостах, имеет смысл пересмотреть разметку диска и отделить контейнерные данные от системного раздела. Для небольших проектов это особенно важно даже на компактном VDS, где запас по /var невелик.

Что ещё проверить на Debian и Ubuntu

journald и системные логи

journalctl --disk-usage
journalctl --vacuum-time=7d
journalctl --vacuum-size=500M

Если journald не ограничен, он может незаметно занять значительную часть /var.

apt-кэш

apt clean

Обычно это не главный источник проблемы, но в аварийной ситуации каждый освобождённый гигабайт полезен.

Временные файлы

du -xh /tmp --max-depth=1 | sort -h
du -xh /var/tmp --max-depth=1 | sort -h

Некоторые пайплайны, распаковка архивов и сборки образов активно используют именно эти каталоги.

Пошаговый аварийный runbook

  1. Проверьте df -h и df -i.
  2. Посмотрите распределение объёма через du в /var, /var/lib/docker и /var/lib/containerd.
  3. Найдите deleted-файлы командой lsof +L1.
  4. Для Docker начните с docker system prune и docker builder prune.
  5. Проверьте и при необходимости сократите логи контейнеров.
  6. Для containerd используйте crictl, ctr или nerdctl в зависимости от стека.
  7. После освобождения места перепроверьте запуск контейнеров и состояние приложения.
  8. Сразу после инцидента настройте профилактику: ротацию логов, регулярную очистку cache и мониторинг inode.

Главное правило: не удаляйте вручную внутренние каталоги overlayfs, если проблему можно решить штатными средствами рантайма. Быстрый путь тут часто оказывается самым рискованным.

Профилактика: как не ловить ENOSPC снова

Ограничьте логи контейнеров

Для Docker с json-file обязательно задайте max-size и max-file. Для containerd и Kubernetes проверьте политику логирования на уровне вашего стека.

Регулярно чистите build cache

На CI-хостах полезен cron или systemd timer для плановой очистки. Важно подобрать retention так, чтобы не убить скорость сборок без необходимости.

Мониторьте и байты, и inode

Одна только метрика свободного места не даёт полной картины. Для контейнерных хостов это обязательный минимум наблюдаемости.

Разделяйте system и container data

Если сервер изначально работает как контейнерный хост, лучше держать данные рантайма на отдельном разделе. Тогда переполнение overlay2 не уронит весь системный /var.

Пересмотрите lifecycle локальных образов

На узле должны оставаться только те image, которые реально нужны для текущей работы и отката. Остальное лучше загружать из registry по необходимости.

Настройте алерты заранее

  • свободное место меньше 15%;
  • свободные inode меньше 15%;
  • аномальный рост /var/lib/docker или /var/lib/containerd;
  • слишком большие логи контейнеров;
  • disk pressure на Kubernetes-узлах.

Итог

Ошибка overlayfs: no space left on device в Docker и containerd почти никогда не лечится одной магической командой. Нужна короткая диагностика: df -h, df -i, du, проверка runtime и поиск deleted-файлов.

Для Docker обычно помогают штатные очистки, контроль логов и build cache. Для containerd важно использовать правильный namespace и корректные инструменты — ctr, crictl или nerdctl. А если вы упёрлись в inode, нужно убирать не самые большие файлы, а самые массовые наборы мелких файлов.

И главное: если не ограничить логи, не навести порядок в кэше и не мониторить inode, тот же инцидент повторится снова — как обычно, в самый неудобный момент.

Поделиться статьей

Вам будет интересно

Debian/Ubuntu: как исправить left-over process in control group у systemd OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: как исправить left-over process in control group у systemd

Предупреждение systemd о left-over process in control group означает, что после остановки сервиса в его cgroup остались процессы. ...
Debian/Ubuntu: failed to create shim task и OCI runtime create failed в Docker — как найти причину и быстро исправить OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: failed to create shim task и OCI runtime create failed в Docker — как найти причину и быстро исправить

Если контейнер в Debian или Ubuntu не запускается и Docker пишет failed to create shim task или OCI runtime create failed, причину ...
Debian/Ubuntu: SSH Broken pipe и Connection reset by peer — причины и пошаговая диагностика OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: SSH Broken pipe и Connection reset by peer — причины и пошаговая диагностика

Если SSH на Debian или Ubuntu обрывается с Broken pipe, Connection reset by peer или зависает после простоя, причина часто не в са ...