CLI AI

Логи docker забили диск: обрезать и ограничить

2026-07-11

truncate -s 0 "$(docker inspect --format '{{.LogPath}}' api)" очищает лог работающего контейнера и освобождает место сразу, без перезапуска. rm здесь применять нельзя: демон продолжает писать в удалённый файл, место не возвращается, а docker logs не работает до перезапуска контейнера.

1. Сначала понять, сколько занял docker

clai
$ clai сколько места занимает docker→ docker system dfTYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLEImages          48        14        28.88GB   20GB (69%)Containers      17        10        4.631MB   513.8kB (11%)Local Volumes   38        7         6.349GB   4.084GB (64%)Build Cache     181       0         0B        0B

Логов в этой таблице не видно вообще — строка Containers считает только слой записи. Если df показывает забитый диск, а docker system df спокоен, виноваты логи.

2. Найти контейнер, который пишет больше всех

clai
$ clai покажи размер лог-файла каждого контейнера, по убыванию→ docker ps -q | xargs docker inspect --format '{{.LogPath}} {{.Name}}' | while read -r p n; do printf '%s\t%s\n' "$(du -h "$p" | cut -f1)" "${n#/}"; done | LC_ALL=C sort -rh | head -36.1M	api3.2M	worker1.9M	cache

LogPath — единственный надёжный способ узнать путь: у rootful и rootless установки он разный. LC_ALL=C не украшение: в локали, где разделитель дробной части запятая, sort -h ставит 844K выше 6.1M.

3. Обрезать лог живого контейнера

clai
$ clai очисти лог контейнера api не останавливая его→ truncate -s 0 "$(docker inspect --format '{{.LogPath}}' api)"

Контейнер продолжает писать в тот же файловый дескриптор, поток не рвётся, место возвращается немедленно. Это та самая команда, которая нужна во время инцидента.

4. Ловушка: rm вместо truncate

clai
$ clai удали лог-файл контейнера api→ rm "$(docker inspect --format '{{.LogPath}}' api)"⚠ CAUTION — после этого docker logs не работает до перезапуска контейнера

docker logs отвечает Error grabbing logs: open …-json.log: no such file or directory, и файл сам не появляется. Демон держит удалённый файл открытым, поэтому место тоже не освобождается — вывод потерян, а проблема осталась.

5. Чтобы это не повторилось

clai
$ clai запусти контейнер с ротацией лога по 10 мегабайт и тремя файлами→ docker run -d --log-opt max-size=10m --log-opt max-file=3 --name api alpine sleep 600

Размер одного файла, умноженный на их число, и есть потолок — здесь 30 МБ. Ставьте его каждому болтливому контейнеру.

6. Проверить, есть ли лимит у работающего контейнера

clai
$ clai покажи настройки логирования контейнера api→ docker inspect -f '{{json .HostConfig.LogConfig}}' api{"Type":"json-file","Config":{"max-file":"3","max-size":"10m"}}

Пустой "Config":{} означает, что лимита нет вовсе и файл будет расти, пока не кончится диск. Именно так выглядит контейнер, запущенный без этих опционов.

Gotchas

  • Обрезка освобождает только активный файл. Контейнер с max-size=1m --log-opt max-file=2 написал 20000 строк, и docker logs показывал их все. После обрезки активного файла осталось 10122 строки — остальное лежит в повёрнутом …-json.log.1. Повёрнутые файлы удаляют, активный обрезают.
  • daemon.json не действует на существующие контейнеры. log-opts в /etc/docker/daemon.json читается при создании контейнера. Работающие живут со старыми настройками, пока их не пересоздать.
  • sort -h зависит от локали. В русской или немецкой локали 6.1M не разбирается как число, и самый жирный лог уезжает в середину списка. Перед sort нужен LC_ALL=C.

Related questions

Почему docker system df не показывает логи? Он считает образы, слои записи контейнеров, тома и кеш сборки. Json-логи лежат рядом, в каталоге контейнера, и в эту таблицу не попадают.

Как ограничить логи сразу всем контейнерам? Прописать "log-driver": "json-file" и "log-opts": {"max-size": "10m", "max-file": "3"} в /etc/docker/daemon.json, перезапустить демон и пересоздать контейнеры.

Можно ли вообще не писать логи на диск? Да, --log-driver none отключает сбор, но тогда docker logs не покажет ничего. Компромисс — драйвер local, у него ротация включена по умолчанию.

See also

CliAI превращает формулировку выше в точную команду и помечает вариант с rm меткой CAUTION до запуска. Поставить одной строкой.