Друзья, сегодня мы закроем один важный пробел. В прошлой статье я рассказал про Docker logs вообще — про драйверы, ротацию, централизованный сбор. А сегодня давайте сфокусируемся на самом главном: как правильно смотреть логи прямо сейчас, в консоли, когда контейнер падает и нужно срочно понять почему.
Потому что знать docker logs — мало. Нужно знать, как вытащить из этой команды максимум, не утонуть в потоке и увидеть именно то, что нужно.
База: что такое docker logs и откуда оно берётся
Напомню базовый принцип: Docker перехватывает всё, что процесс внутри контейнера пишет в stdout (стандартный вывод) и stderr (стандартный вывод ошибок). Команда docker logs просто показывает этот поток.
```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 logs может не работать
Прежде чем мы углубимся в тонкости, давайте разберём ситуацию: вы запускаете docker logs, а там пусто. Или не то, что ожидали.
Причины:
1. Приложение пишет не в stdout/stderr. Например, настроено логирование в файл внутри контейнера. Это частая ошибка новичков. Исправляется настройкой приложения.
2. Используется другой драйвер логирования. Если контейнер запущен с драйвером syslog или fluentd, docker logs ничего не покажет .
3. Контейнер уже удалён. Если контейнер запускался с --rm, после остановки он исчезает вместе с логами.
Проверить драйвер:
bash
docker inspect --format='{{.HostConfig.LogConfig.Type}}' my-container
Если там не json-file и не local, docker logs вам не поможет.
Продвинутая фильтрация: таймстемпы — наше всё
Самое мощное, что есть в docker logs — фильтрация по времени .
```bash
Логи за последние 5 минут
docker logs --since 5m my-container
Логи за последние 2 часа
docker logs --since 2h my-container
Логи с конкретного момента
docker logs --since "2026-03-04T14:30:00" my-container
Логи до конкретного момента
docker logs --until "2026-03-04T15:00:00" my-container
Окно: с 14:30 до 15:00
docker logs --since "2026-03-04T14:30:00" --until "2026-03-04T15:00:00" my-container ```
Это невероятно удобно, когда ошибка случилась 10 минут назад, и вы не хотите листать тысячи строк.
Поддерживаются форматы:
- RFC3339: 2026-03-04T14:30:00Z
- RFC3339 с наносекундами: 2026-03-04T14:30:00.123456789Z
- Относительные: 30m, 2h, 1d, 1w, 1y
Поиск и grep: джедайские техники
docker logs не умеет фильтровать по содержимому, но Unix умеет. Используем grep.
```bash
Найти все ошибки
docker logs my-container 2>&1 | grep ERROR
Найти все ошибки, игнорируя регистр
docker logs my-container 2>&1 | grep -i error
Найти все ошибки и показать контекст (2 строки до и после)
docker logs my-container 2>&1 | grep -B2 -A2 ERROR
Исключить шум
docker logs my-container 2>&1 | grep -v "health check"
Подсветка найденного
docker logs my-container 2>&1 | grep --color=always ERROR
Следить и фильтровать одновременно
docker logs -f my-container 2>&1 | grep --line-buffered ERROR ```
Флаг --line-buffered критически важен для grep в реальном времени — без него вывод может буферизоваться и приходить пачками, а не мгновенно.
Если grep сложный, используем awk
```bash
Вывести только время и сообщение об ошибке
docker logs my-container 2>&1 | awk '/ERROR/ {print $1, $2, $NF}'
Посчитать количество ошибок по типам
docker logs my-container 2>&1 | awk '/ERROR/ {count[$NF]++} END {for (e in count) print e, count[e]}' ```
Работа с несколькими контейнерами
Когда сервисов много, хочется видеть всё сразу.
Docker Compose
Если контейнеры описаны в docker-compose.yml:
```bash
Логи всех сервисов
docker-compose logs
Логи всех сервисов, последние 100 строк
docker-compose logs --tail=100
В реальном времени
docker-compose logs -f
Логи конкретного сервиса
docker-compose logs web ```
Несколько контейнеров без Compose
```bash
Логи всех запущенных контейнеров (как получится)
docker logs $(docker ps -q)
С именами контейнеров для ясности
for c in $(docker ps -q); do echo "=== $c ===" docker logs --tail 10 $c done ```
multitail для Docker
Есть специальная утилита docker-multitail, но можно обойтись стандартным multitail:
bash
multitail -l 'docker logs -f container1' -l 'docker logs -f container2'
Форматирование вывода: когда нужно больше деталей
Иногда стандартного docker logs мало. Хочется видеть имя контейнера, его ID, временные метки. Тут помогает шаблонизация.
Шаблоны в docker inspect
Узнать путь к файлу с логами на хосте:
bash
docker inspect --format='{{.LogPath}}' my-container
docker logs --details
Если контейнеру при запуске передавались --log-opt с тегами, их можно показать:
bash
docker logs --details my-container
Использование docker events
Для отладки можно смотреть события самого Docker:
bash
docker events --filter 'container=my-container'
Но это про события (старт, стоп, смерть), а не про логи приложения.
Цветной вывод: чтобы глаза не болели
Чёрно-белые логи утомляют. Давайте добавим цвета.
Самый простой способ — через grep
```bash
Подсветка всех вхождений ERROR красным
docker logs -f my-container | grep --color=always -E "ERROR|$" ```
Хитрость с |$ заставляет grep выводить все строки, но подсвечивать только ERROR.
Используем ccze
Если установить ccze, можно получить красивую раскраску:
bash
docker logs my-container | ccze -A
Используем multitail с цветами
multitail умеет раскрашивать по паттернам:
bash
multitail -c /var/lib/docker/containers/*/*-json.log
Работа с большими логами: когда всё плохо
Бывает, что контейнер навалил столько логов, что docker logs виснет или выдаёт мегабайты текста.
Стратегия 1: не используйте docker logs
Обращайтесь напрямую к файлу:
```bash
Получаем путь к файлу лога
LOG_PATH=$(docker inspect --format='{{.LogPath}}' my-container)
Смотрим последние 100 строк
tail -n 100 $LOG_PATH
Ищем ошибки
grep ERROR $LOG_PATH
Следим
tail -f $LOG_PATH ```
Это быстрее, потому что минуется прослойка Docker.
Стратегия 2: пагинация через less
bash
docker logs my-container | less
В less можно искать, листать, и это не повесит терминал.
Стратегия 3: экспорт в файл
bash
docker logs my-container > /tmp/my-container.log
Потом можно анализировать любимыми инструментами.
Интерактивная отладка: логи + процесс
Иногда нужно не просто смотреть логи, а одновременно видеть, что происходит с контейнером.
docker attach
Команда docker attach подключает ваш терминал к консоли контейнера — вы видите логи и можете отправлять сигналы (Ctrl+C остановит контейнер!).
bash
docker attach my-container
Внимание: если нажать Ctrl+C, сигнал уйдёт в контейнер. Если хотите просто отсоединиться, нажмите Ctrl+P Ctrl+Q.
docker exec для диагностики
Пока смотрите логи, можно залезть внутрь и посмотреть процессы:
```bash
В одном терминале
docker logs -f my-container
В другом
docker exec -it my-container ps aux ```
Сравнение логов разных версий контейнера
При обновлении версии образа полезно сравнить логи до и после.
```bash
Логи старого контейнера (ещё живого)
docker logs old-container > old.log
Логи нового
docker logs new-container > new.log
Сравниваем
diff -u old.log new.log | less ```
Частые сценарии и их решения
Сценарий 1: Контейнер постоянно перезапускается и быстро падает
```bash
Смотрим последние строки перед смертью
docker logs --tail 50 --timestamps my-container
Если контейнера уже нет, но он не удалён
docker logs --tail 50 my-container
Если контейнер удаляется, используем --rm, логи потеряны — меняем политику
```
Лучшее решение: временно убрать --rm, запустить контейнер без него, дать упасть, потом посмотреть логи.
Сценарий 2: Логов слишком много, глаза разбегаются
```bash
Оставляем только ошибки и предупреждения
docker logs my-container 2>&1 | grep -E "ERROR|WARN|FATAL"
Считаем частоту ошибок
docker logs my-container 2>&1 | grep ERROR | awk '{print $NF}' | sort | uniq -c | sort -rn ```
Сценарий 3: Нужно понять, что было до ошибки
```bash
10 строк до и после каждого вхождения ERROR
docker logs my-container 2>&1 | grep -B10 -A10 ERROR | less ```
Сценарий 4: Логи в реальном времени, но только интересное
bash
docker logs -f my-container 2>&1 | while read line; do
if [[ "$line" == *"ERROR"* ]] || [[ "$line" == *"Exception"* ]]; then
echo "$(date +%H:%M:%S) $line"
fi
done
Сценарий 5: Мониторинг нескольких контейнеров в реальном времени
Скрипт, который показывает логи всех контейнеров с префиксом:
```bash
!/bin/bash
for c in $(docker ps -q); do name=$(docker inspect --format='{{.Name}}' $c | sed 's/\///') docker logs -f $c 2>&1 | sed "s/^/[$name] /" & done wait ```
Логи и деплой: что делать перед обновлением
Перед тем как обновлять контейнер, сохраните логи старой версии:
bash
docker logs my-app > my-app-$(date +%Y%m%d-%H%M%S).log
Если после обновления всё сломалось, у вас будет с чем сравнивать.
Производительность: сколько можно смотреть
docker logs -f практически не грузит систему, если контейнер пишет немного. Но если логов миллион строк в минуту, даже простой вывод в терминал может загрузить процессор.
В таких случаях: - Используйте фильтры - Не выводите в терминал, пишите в файл - Используйте прямой доступ к файлам
Типичные ошибки при работе с docker logs
Ошибка 1: Забыть про 2>&1
```bash
Так вы увидите только stdout, stderr потеряется
docker logs my-container | grep ERROR
Надо так
docker logs my-container 2>&1 | grep ERROR ```
Ошибка 2: Ждать мгновенной реакции от grep без --line-buffered
```bash
Неправильно — вывод будет пачками
docker logs -f my-container | grep ERROR
Правильно
docker logs -f my-container | grep --line-buffered ERROR ```
Ошибка 3: Пытаться открыть гигабайтный лог в less без ограничений
```bash
Плохо — less загрузит всё
docker logs huge-container | less
Хорошо — только последние 1000 строк
docker logs --tail 1000 huge-container | less ```
Ошибка 4: Игнорировать таймстемпы при расследовании
Всегда используйте --timestamps, чтобы понимать хронологию.
Ошибка 5: Не проверять драйвер логирования
Убедитесь, что docker logs вообще может работать с этим контейнером.
Коротко: шпаргалка
| Задача | Команда |
|--------|---------|
| Последние N строк | docker logs --tail N контейнер |
| Следить в реальном времени | docker logs -f контейнер |
| С определённого времени | docker logs --since 10m контейнер |
| До определённого времени | docker logs --until 2026-03-04T15:00 контейнер |
| С таймстемпами | docker logs -t контейнер |
| Найти ошибки | docker logs контейнер 2>&1 \| grep ERROR |
| Найти ошибки и следить | docker logs -f контейнер 2>&1 \| grep --line-buffered ERROR |
| Получить путь к файлу лога | docker inspect --format='{{.LogPath}}' контейнер |
| Логи всех сервисов в compose | docker-compose logs -f |
Вместо заключения
docker logs — это, пожалуй, самая часто используемая команда при работе с контейнерами. И при этом самая недооценённая. Многие знают только docker logs -f и на этом останавливаются.
А ведь умение быстро вытащить логи за нужный промежуток, отфильтровать лишнее, подсветить важное — это разница между "я ищу ошибку час" и "я нашёл ошибку за минуту".
Освойте эти приёмы. Они не сложные, но каждый из них экономит время. А время, как известно, единственный невосполнимый ресурс.