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

Docker log driver: ротация логов и защита диска от переполнения

Логи контейнеров легко заполняют диск: приложение шумит в stdout/stderr, ротации нет — и раздел уходит в 100%, а сервисы падают. Разбираем log driver в Docker, настройку json-file rotation и варианты journald/fluentd.
Docker log driver: ротация логов и защита диска от переполнения

Переполненный диск из‑за логов контейнеров — один из самых частых «внезапных» инцидентов на серверах с Docker. Сценарий типовой: приложение начинает активно писать в stdout/stderr, Docker складывает всё в файл, ротации нет (или она настроена только в logrotate на хосте и не затрагивает контейнерные логи), и через несколько часов или дней вы ловите переполнение раздела, падение сервисов и ошибки записи в файловую систему.

Ниже — практическая инструкция: как устроены log driver в Docker, как включить json-file log rotation параметрами max-size и max-file, что меняется при переходе на journald и когда уместен fluentd. В конце — диагностика, безопасная уборка и чек-лист выбора.

Как Docker хранит логи и почему это приводит к переполнению диска

По умолчанию Docker использует драйвер логирования json-file. Это означает:

  • всё, что контейнер пишет в stdout/stderr, Docker пишет в файлы на хосте;
  • файлы лежат внутри каталога данных Docker (обычно /var/lib/docker);
  • если ротация не включена, файл растёт без ограничений.

Ключевой момент: многие админы считают, что «у меня же есть logrotate». Но классические правила logrotate для /var/log не управляют логами Docker автоматически. В итоге контейнеры начинают «втихаря» раздувать /var/lib/docker, пока не упрётесь в 100%.

Где именно лежат логи при json-file

Файлы логов контейнера находятся по пути вида:

/var/lib/docker/containers/<container-id>/<container-id>-json.log

Если Docker‑директория на том же разделе, что и система или данные приложений, один «болтливый» контейнер способен положить весь узел.

Быстрая диагностика: кто съел место и сколько

Сначала подтверждаем, что проблема действительно в логах Docker, и оцениваем масштаб.

Проверить общий disk usage

df -h

Если / или /var близки к 100%, переходим к Docker.

Оценить общий размер Docker

docker system df

Команда покажет объёмы по образам, контейнерам, volumes и build cache. Но файлы логов json-file не всегда очевидны в этой сводке, поэтому дополнительно проверяем директорию контейнеров.

Найти самые большие файлы *-json.log

sudo du -ah /var/lib/docker/containers | sort -h | tail -n 30

Обычно сразу видно один или несколько файлов *-json.log на гигабайты.

Связать container-id с именем контейнера

docker ps --no-trunc

Либо точечно:

docker inspect --format '{{.Name}} {{.Id}}' <container-id>

Важно: если просто удалить файл лога, Docker может продолжать писать в «удалённый» inode, и место не освободится до перезапуска контейнера или демона. Поэтому «rm и всё» — частая причина, почему место так и не вернулось.

Схема: где лежат json-file логи Docker и почему они растут без ротации

Правильное решение №1: json-file log rotation (max-size/max-file)

Если вам подходит хранение логов на диске и вы привыкли смотреть их через docker logs, самый простой и популярный вариант — включить ротацию для json-file.

Включить ротацию глобально в daemon.json

Откройте (или создайте) файл:

/etc/docker/daemon.json

Пример конфигурации:

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

Смысл параметров:

  • max-size — максимальный размер одного файла перед ротацией;
  • max-file — сколько файлов хранить (старые будут удаляться).

Перезапустите Docker:

sudo systemctl restart docker

Учтите: глобальная настройка применяется к новым контейнерам. Уже запущенные продолжат работать со старыми параметрами, пока вы их не пересоздадите (или не смените драйвер через пересоздание сервиса в Compose/Swarm).

Настроить ротацию для конкретного контейнера

Если глобально менять политику нельзя, задайте опции на уровне контейнера:

docker run --log-driver json-file --log-opt max-size=10m --log-opt max-file=5 your-image

В Docker Compose это выглядит так (YAML):

services:
  app:
    image: your-image
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "5"

Практичные пресеты max-size/max-file

  • большинство веб‑приложений: max-size 10–50m, max-file 3–10;
  • «шумные» воркеры/очереди: max-size 50–200m, max-file 2–5;
  • на время отладки: увеличивайте окно (обычно max-file), но держите диск под мониторингом.

Что будет с docker logs

docker logs продолжит работать, но история ограничится тем, что поместилось в окно ротации. Это нормальный и полезный компромисс между «посмотреть хвост» и гарантировать живой диск.

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

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

Независимо от выбранного драйвера логирования, добавьте мониторинг заполнения файловых систем и алерты хотя бы на 80% и 90% — это почти всегда дешевле, чем аварийная уборка в разгар инцидента.

Правильное решение №2: journald как драйвер логирования

Если у вас Linux с systemd, часто разумнее отправлять контейнерные логи в journald. Тогда Docker не управляет файлами логов напрямую, а вы используете уже знакомые политики хранения журнала.

Плюсы journald

  • централизованные лимиты (по размеру, времени, свободному месту);
  • фильтрация через journalctl, удобнее разбирать инциденты «на хосте»;
  • меньше риска, что один контейнер раздует один монолитный файл.

Минусы journald

  • логи становятся «системными»: привычные пайплайны, которые читают файлы, могут не подойти;
  • если journald не ограничен, проблема просто переедет в журнал.

Как включить journald в Docker

В /etc/docker/daemon.json:

{
  "log-driver": "journald"
}

Перезапуск:

sudo systemctl restart docker

Базовый просмотр:

journalctl -u docker --no-pager -n 200

Также можно продолжать использовать docker logs, но поведение зависит от версии Docker и сборки.

Обязательная часть: лимиты journald

Проверьте параметры в /etc/systemd/journald.conf. На практике чаще всего нужны:

  • SystemMaxUse — верхний предел диска под журнал;
  • SystemKeepFree — сколько места всегда оставлять свободным;
  • MaxRetentionSec — ограничение по времени хранения;
  • SystemMaxFileSize — максимальный размер сегмента.

После изменений перезапустите journald:

sudo systemctl restart systemd-journald

Настройка journald и лимитов хранения для логов Docker

Правильное решение №3: fluentd для централизованного сбора

Когда контейнеров много, нужна единая политика и поиск по логам, обычно переходят к централизованному сбору. В Docker для этого часто используют fluentd как log driver.

Когда fluentd оправдан

  • нужны поиск, алерты и дашборды по логам;
  • нужно хранение дольше, чем позволяет локальный диск;
  • нужно обогащение метаданными (имя контейнера, labels, node).

Риски и нюансы fluentd

  • логирование зависит от доступности fluentd: при проблемах возможны задержки или потери (зависит от режима и буферов);
  • нужно продумать backpressure и буферизацию, иначе «лог‑шторм» ударит по CPU/сети.

Минимальная настройка fluentd

Глобально в daemon.json (пример):

{
  "log-driver": "fluentd",
  "log-opts": {
    "fluentd-address": "127.0.0.1:24224",
    "tag": "docker.{{.Name}}"
  }
}

Дальше на стороне fluentd настраиваются буферы, очереди и доставка в целевое хранилище.

Почему не стоит настраивать logrotate на *-json.log

Иногда пытаются написать правила logrotate для *-json.log. На практике это часто даёт нестабильный результат и неприятные эффекты:

  • Docker держит файл открытым; переименование не гарантирует освобождение места;
  • copytruncate может обрезать лог в момент записи, ломая JSON‑структуру;
  • при высокой нагрузке возможны гонки между Docker и logrotate.

Если вы остаетесь на json-file — включайте нативную ротацию max-size/max-file. Если нужна системная политика — используйте journald. Если нужен сбор «в одно место» — fluentd и корректная буферизация.

Если параллельно усиливаете безопасность контейнерного хоста, пригодится разбор: Docker, iptables и nftables: что происходит с правилами фаервола.

Что делать, если диск уже заполнен логами (аварийный план)

Когда места нет, цель — быстро вернуть возможность записи на диск, а затем внедрить постоянную политику.

1) Найти топ по объёму и определить виновника

sudo du -h /var/lib/docker/containers/*/*-json.log 2>/dev/null | sort -h | tail -n 20

2) Временно освободить место безопасно

Самый безопасный путь — пересоздать контейнер с включённой ротацией и (если нужно) временно снизить уровень логирования приложения. Если нужно «прямо сейчас» и контейнер можно перезапустить, можно обнулить файл (не удалять):

sudo truncate -s 0 /var/lib/docker/containers/<container-id>/<container-id>-json.log

Затем перезапустить контейнер:

docker restart <container-id>

После этого обязательно внедрите постоянное решение (ротация или смена драйвера), иначе инцидент повторится.

3) Проверить, не держатся ли удалённые файлы

Если ранее логи удалялись через rm, место могло не вернуться. Проверка:

sudo lsof +L1 | grep /var/lib/docker | head

Если видите строки с deleted и большим размером, помогает перезапуск соответствующего процесса (часто dockerd или конкретного контейнера).

Чек-лист: как выбрать log driver под вашу задачу

  • Нужно просто и привычно, логи смотрим через docker logsjson-file + max-size/max-file.
  • Нужны единые лимиты на хосте и «системный» подходjournald + настройки journald.conf.
  • Нужен централизованный сбор, поиск, долгий ретеншнfluentd (или аналог) + продуманная доставка и буферы.

Минимальный продовый стандарт для одного сервера

Если вы администрируете 1–несколько Docker‑хостов без полноценного лог‑стека, практичный минимум обычно такой:

  • оставить json-file, но включить ротацию: max-size 10–50m и max-file 5–10;
  • держать /var/lib/docker на разделе с понятным запасом и мониторить заполнение;
  • добавить алерты по диску хотя бы на 80% и 90%;
  • для особо шумных сервисов — снижать уровень логирования приложения и ограничивать спам по ошибкам.

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

Если Docker‑хостов становится больше, чем «пара серверов», имеет смысл заранее продумать масштабирование: отдельные диски под данные, понятные лимиты и ресурсные резервы. В таких сценариях часто удобнее разворачивать окружения на VDS с предсказуемыми ресурсами и возможностью быстро увеличить объём.

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

Проверка после внедрения

После включения ротации или смены драйвера проверьте:

  • что новые контейнеры действительно получили нужный log driver;
  • что логи доступны инженерам (через docker logs или journalctl);
  • что рост потребления диска стал ограниченным;
  • что при перезапусках не теряются важные диагностические события (критичные события лучше отправлять отдельным каналом).

Проверить драйвер у контейнера можно так:

docker inspect --format '{{.HostConfig.LogConfig.Type}} {{json .HostConfig.LogConfig.Config}}' <container-name-or-id>

Если хотите, следующий шаг — подобрать значения max-size и max-file от расчёта: по средней скорости логирования, допустимому окну хранения и реальному размеру диска/раздела.

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

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

Debian/Ubuntu: конфликт systemd-resolved DNSStubListener на 127.0.0.53 с dnsmasq, Unbound и BIND OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: конфликт systemd-resolved DNSStubListener на 127.0.0.53 с dnsmasq, Unbound и BIND

Если локальный DNS в Debian или Ubuntu не стартует с ошибкой address already in use, причина часто в systemd-resolved и DNSStubLis ...
Debian/Ubuntu: как исправить NFS mount.nfs: access denied by server while mounting OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: как исправить NFS mount.nfs: access denied by server while mounting

Ошибка mount.nfs: access denied by server while mounting в Debian и Ubuntu обычно указывает на проблему на стороне NFS-сервера: не ...
Debian/Ubuntu: как устранить конфликт systemd-resolved DNSStubListener с BIND9, dnsmasq и AdGuard Home OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: как устранить конфликт systemd-resolved DNSStubListener с BIND9, dnsmasq и AdGuard Home

Если в Debian или Ubuntu DNS-сервер не стартует из-за ошибки port 53 busy, часто причина в systemd-resolved с локальным слушателем ...