Docker logs: полное руководство по работе с логами контейнеров

Друзья, сегодня мы поговорим о логировании в Docker. Это тема, которая рано или поздно встаёт перед каждым, кто начинает активно использовать контейнеризацию. Сначала всё просто: запустил контейнер, посмотрел docker logs, увидел ошибку, починил. Но когда контейнеров становится много, когда они перезапускаются, когда диски начинают заполняться непонятно чем — приходит понимание, что к логам нужен системный подход.

Я собрал в этой статье всё, что знаю про Docker logs: от базовых команд до продвинутых настроек, ротации и интеграции с внешними системами. Поехали.

Что такое логи в Docker и откуда они берутся

В основе философии Docker лежит принцип: приложение должно писать логи в stdout (стандартный вывод) и stderr (стандартный вывод ошибок) . Всё, что приложение отправляет туда, Docker перехватывает и обрабатывает в соответствии с настроенным драйвером логирования.

Это гениально просто: разработчику не нужно думать о файлах, путях и ротации. Просто пиши в консоль, а Docker разберётся. Или почти разберётся — об этом мы поговорим позже.

Логи делятся на два типа : - Логи самого Docker daemon — что происходит с Docker как с сервисом - Логи контейнеров — то, что выводят ваши приложения

Где искать логи Docker daemon

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

Местоположение зависит от ОС :

| Операционная система | Расположение логов Docker daemon | |---------------------|-----------------------------------| | Linux (systemd) | journalctl -xu docker.service | | Linux (старые системы) | /var/log/syslog или /var/log/messages | | macOS | ~/Library/Containers/com.docker.docker/Data/log/vm/dockerd.log | | Windows (WSL2) | %LOCALAPPDATA%\Docker\log\vm\dockerd.log | | Windows (нативные контейнеры) | В Event Log |

В Linux проще всего смотреть так: ```bash

Все логи Docker daemon

sudo journalctl -u docker.service

Последние 50 строк и следить дальше

sudo journalctl -u docker.service -f -n 50 ```

Если нужно включить режим отладки для Docker daemon, отредактируйте /etc/docker/daemon.json : json { "debug": true, "log-level": "debug" } После этого перезапустите Docker: bash sudo systemctl restart docker

Основы работы с docker logs

Базовая команда

Сердце всего логирования в Docker — команда docker logs. Она показывает всё, что контейнер отправил в stdout/stderr .

```bash

Показать все логи контейнера

docker logs my-container

Показать последние 50 строк

docker logs --tail 50 my-container

Следить за логами в реальном времени (как tail -f)

docker logs -f my-container

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

docker logs -t my-container ```

Важно: команда работает даже для остановленных контейнеров . Docker хранит логи, пока контейнер не удалён (и даже дольше, если настроено).

Фильтрация по времени

Одна из самых полезных возможностей — смотреть логи за определённый период .

```bash

Логи за последние 30 минут

docker logs --since 30m my-container

Логи за последние 2 часа

docker logs --since 2h my-container

Логи с конкретного момента

docker logs --since "2026-03-04T10:00:00" my-container

Логи до конкретного момента

docker logs --until "2026-03-04T11:00:00" my-container

Комбинация: окно с 10:00 до 11:00

docker logs --since "2026-03-04T10:00:00" --until "2026-03-04T11:00:00" my-container ```

Поддерживаются форматы: RFC3339, RFC3339Nano, 2006-01-02T15:04:05, а также относительные значения: 30m, 2h, 1d .

Поиск и фильтрация

docker logs сам по себе не умеет фильтровать по содержимому, но это легко делается через grep :

```bash

Найти все ошибки

docker logs my-container 2>&1 | grep ERROR

Исключить шум

docker logs my-container 2>&1 | grep -v "health check"

Комбинация с tail и grep

docker logs -f my-container 2>&1 | grep --line-buffered "Exception" ```

Флаг 2>&1 перенаправляет stderr в stdout, чтобы grep видел всё.

Логи Docker Compose

Если вы используете Docker Compose, смотреть логи ещё удобнее :

```bash

Логи всех сервисов

docker-compose logs

Логи конкретного сервиса

docker-compose logs web-backend

В реальном времени

docker-compose logs -f

Последние 100 строк конкретного сервиса

docker-compose logs --tail=100 database ```

Где физически лежат логи контейнеров

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

/var/lib/docker/containers/<container_id>/<container_id>-json.log

Это обычные текстовые файлы в формате JSON (каждая строка — JSON-объект с полями log, stream, time). К ним можно обращаться напрямую, минуя docker logs :

```bash

Получить путь к лог-файлу контейнера

docker inspect --format='{{.LogPath}}' my-container

Быстрый поиск по файлу (быстрее, чем через docker logs для больших файлов)

grep ERROR $(docker inspect --format='{{.LogPath}}' my-container)

Хвост файла напрямую

tail -f $(docker inspect --format='{{.LogPath}}' my-container) ```

Прямая работа с файлами даёт преимущества в производительности на больших логах и позволяет использовать все мощные инструменты Unix.

Проблема: логи съедают весь диск

Это классика жанра. Контейнер работает, пишет логи, Docker складывает их в файл. И ничего не удаляет. Месяц, два, три — и диск забит под завязку .

Решение проблемы — ротация логов.

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

Самый правильный способ — настроить ротацию на уровне Docker daemon. Для этого редактируем /etc/docker/daemon.json :

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

Где: - max-size — максимальный размер одного лог-файла (10 мегабайт в примере) - max-file — максимальное количество файлов (3 штуки)

После изменений перезапускаем Docker: bash sudo systemctl restart docker

Важно: настройки применяются только к новым контейнерам. Существующие нужно пересоздать .

Можно использовать и другой драйвер — local, он тоже поддерживает ротацию : json { "log-driver": "local", "log-opts": { "max-size": "10m", "max-file": "3" } }

Настройка для конкретного контейнера

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

bash docker run -d \ --name my-app \ --log-driver json-file \ --log-opt max-size=10m \ --log-opt max-file=5 \ nginx

Настройка в docker-compose.yml

Для Compose-проектов настройки добавляются в каждый сервис :

```yaml version: "3"

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

Ручная очистка

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

```bash

Для всех контейнеров сразу

sudo truncate -s 0 /var/lib/docker/containers//-json.log

Для конкретного контейнера

sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' my-container) ```

Контейнер при этом может работать, логи продолжат писаться с нуля.

Драйверы логирования: выбираем свой

Docker поддерживает множество драйверов логирования . Каждый решает свою задачу.

json-file (по умолчанию)

Логи хранятся в JSON-файлах на хосте. Удобно для локальной отладки, поддерживает ротацию. Именно для этого драйвера работает docker logs .

local

Более производительная альтернатива json-file, логи хранятся во внутреннем формате. Тоже поддерживает ротацию .

syslog

Отправляет логи в системный syslog . Настройка глобально: json { "log-driver": "syslog", "log-opts": { "syslog-address": "udp://localhost:514", "tag": "{{.Name}}" } }

Или для конкретного контейнера: bash docker run --log-driver syslog --log-opt syslog-address=udp://192.168.0.42:514 my-container

journald

Интеграция с systemd journal : json { "log-driver": "journald" }

После этого логи можно смотреть через journalctl -u docker.service и фильтровать по контейнерам.

fluentd / logstash

Для отправки в централизованные системы сбора логов (ELK, EFK) : bash docker run \ --log-driver=fluentd \ --log-opt fluentd-address=10.2.3.4:24224 \ --log-opt tag="docker.{{.Name}}" \ my-app

gelf, awslogs, gcplogs

Специализированные драйверы для Graylog, AWS CloudWatch, Google Cloud Logging .

none

Полное отключение логирования. Используйте осторожно.

Важно: docker logs работает только с драйверами, которые сохраняют логи локально: json-file, local, journald . Для остальных он просто ничего не покажет.

Продвинутые техники

Неблокирующий режим

Если приложение пишет логи очень интенсивно, это может тормозить сам контейнер. Docker поддерживает неблокирующий режим с буферизацией :

bash docker run \ --log-opt mode=non-blocking \ --log-opt max-buffer-size=1MB \ my-app

Логи сначала пишутся в буфер в памяти, а оттуда асинхронно отправляются в драйвер.

Просмотр логов всех контейнеров сразу

Иногда нужно увидеть, что пишут все контейнеры одновременно :

```bash

Логи всех запущенных контейнеров

docker logs $(docker ps -q)

С именами контейнеров (через xargs)

docker ps -q | xargs -P 10 -I {} sh -c 'echo "=== {} ===" && docker logs --tail 10 {}' ```

Инспекция настроек логирования

Узнать, какой драйвер использует контейнер :

```bash docker inspect --format='{{.HostConfig.LogConfig.Type}}' my-container

Детальная информация

docker inspect my-container | grep -A 10 LogConfig ```

Поиск контейнеров, которые больше всего пишут в логи

Найти "болтливые" контейнеры можно по размеру лог-файлов :

bash sudo du -d1 -h /var/lib/docker/containers | sort -h

Логи и разработка: best practices

1. Пишите в stdout/stderr

Это главное правило. Не надо писать логи в файлы внутри контейнера — они потеряются при перезапуске, и docker logs их не покажет. Настройте своё приложение так, чтобы логи шли в консоль .

Для популярных инструментов это делается просто: - Nginx: access_log /dev/stdout; error_log /dev/stderr; - Apache: ErrorLog /proc/self/fd/2 - Python (Flask/Django): настроить handler на stdout - Node.js: console.log() уже пишет в stdout

2. Используйте структурированные логи

Когда приложение пишет просто текст, это удобно читать человеку, но неудобно машине. Если вы планируете централизованный сбор и анализ, лучше писать в JSON :

{"timestamp":"2026-03-04T10:00:00Z","level":"ERROR","service":"auth","user_id":12345,"message":"Login failed"}

Такие логи легко парсить, индексировать и анализировать.

3. Не логируйте секреты

Пароли, токены, ключи API не должны попадать в логи. Никогда .

4. Всегда настраивайте ротацию

Даже на тестовых стендах. Один раз настроил — и забыл проблему "диск забит логами" .

5. Используйте метки (labels)

Добавляйте к контейнерам метки — они потом попадут в логи и помогут фильтровать : bash docker run --label environment=production --label service=auth my-app

Централизованный сбор логов

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

Вариант 1: ELK/EFK стек

Классическая связка: Filebeat (или Fluentd) забирает логи из /var/lib/docker/containers/*/*-json.log и отправляет в Elasticsearch, а Kibana показывает.

Вариант 2: Loki

Относительно новый игрок от Grafana Labs. Легче Elasticsearch, оптимизирован именно для логов. Интегрируется с Grafana.

Вариант 3: Платные сервисы

Datadog, New Relic, Middleware — предлагают готовые агенты для сбора логов .

Пример отправки в Middleware через Fluentd : bash docker run \ --log-driver=fluentd \ --log-opt fluentd-address=middleware.io:24224 \ my-app

Диагностика проблем с логами

Проблема: docker logs ничего не показывает

Причины: - Контейнер использует другой драйвер (syslog, fluentd) - Приложение пишет не в stdout/stderr, а в файлы - Контейнер запущен с флагом --rm и уже удалён

Решение: ```bash

Проверить драйвер

docker inspect --format='{{.HostConfig.LogConfig.Type}}' my-container

Посмотреть, куда настроено логирование

docker inspect my-container | grep -A 10 LogConfig ```

Проблема: логи слишком большие, тормозят

Решение: настроить ротацию, использовать прямой доступ к файлам .

Проблема: логи теряются при перезапуске

Проверьте, не используется ли --rm. Если контейнер удаляется, логи пропадают. Используйте внешние драйверы или монтируйте volume для хранения логов, если нужна持久ость.

Проблема: в логах время не совпадает с реальностью

Убедитесь, что на хосте правильное время. Docker использует системное время хоста. Также проверьте, использует ли контейнер правильную временную зону (можно пробросить /etc/localtime).

Чек-лист для настройки логирования в Docker

  • [ ] Все приложения настроены на вывод в stdout/stderr
  • [ ] Настроена глобальная ротация логов (max-size/max-file) в /etc/docker/daemon.json
  • [ ] Или настроена ротация для каждого сервиса в docker-compose
  • [ ] Выбран подходящий драйвер логирования (json-file/local для локальной разработки, fluentd/syslog для прода)
  • [ ] Настроен неблокирующий режим для высоконагруженных приложений
  • [ ] Для продакшена настроен централизованный сбор логов
  • [ ] Настроен мониторинг размера логов (чтобы не пропустить, когда что-то пойдёт не так)
  • [ ] Проверено, что секреты не попадают в логи
  • [ ] Для долгоживущих проектов настроена архивация старых логов

Вместо заключения

Логи в Docker — это одновременно и просто, и сложно. Просто — потому что команда docker logs даёт мгновенный доступ к выводу любого контейнера. Сложно — потому что без правильной настройки ротации и централизованного сбора рано или поздно вы упрётесь в забитый диск или утонете в поиске по сотням файлов.

Главный совет: относитесь к логам как к важной части инфраструктуры с первого дня. Настройте ротацию сразу, выберите подходящий драйвер, а если проект растёт — заложите время на внедрение централизованного сбора.

И помните: хорошие логи экономят часы отладки. Плохие логи создают часы отладки. Выбирайте, по какую сторону баррикад вы хотите быть.