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 даёт мгновенный доступ к выводу любого контейнера. Сложно — потому что без правильной настройки ротации и централизованного сбора рано или поздно вы упрётесь в забитый диск или утонете в поиске по сотням файлов.
Главный совет: относитесь к логам как к важной части инфраструктуры с первого дня. Настройте ротацию сразу, выберите подходящий драйвер, а если проект растёт — заложите время на внедрение централизованного сбора.
И помните: хорошие логи экономят часы отладки. Плохие логи создают часы отладки. Выбирайте, по какую сторону баррикад вы хотите быть.