# Docker logs и journald: выбор драйвера логирования

Индекс LLMS: [llms.txt](/llms.txt)

---

Когда контейнер падает, логи — первое, что нужно увидеть. `docker logs` выглядит просто, но под капотом работает разные драйверы логирования, и выбор влияет на то, как хранятся, вращаются и доступны логи. Вот что стоит знать перед тем, как доверять дефолту.

## Как работает docker logs

Команда `docker logs <container>` читает поток stdout/stderr контейнера и выдаёт его в терминал. За этим стоит **драйвер логирования** — компонент, который определяет, куда именно пишутся данные. По умолчанию это `json-file`: каждый контейнер получает JSON-файл на хосте, в который записываются все строки вывода.

> [!NOTE]
> `docker logs` не читает логи изнутри контейнера напрямую — он обращается к драйверу, который уже хранит эти данные в своём формате и месте.

Драйвер настраивается на уровне демона Docker или отдельного контейнера. Выбор влияет на вращение файлов, доступ к логам из `journalctl`, интеграцию с централизованными системами сбора.

## Драйвер json-file (по умолчанию)

`json-file` — встроенный драйвер без зависимостей. Каждый контейнер создаёт файл вида `/var/lib/docker/containers/<container-id>/<container-id>-json.log`. Формат — JSON-линии: каждая строка содержит `log`, `stream` (stdout или stderr), `time`.

Вращение контролируется двумя флагами:

| Флаг | Описание |
|---|---|
| `max-size` | Максимальный размер одного файла лога (например, `10m`) |
| `max-file` | Количество хранимых ротированных файлов |

Без этих флагов файлы растут без ограничений. На продакшене это прямой путь к заполнению диска.

```bash
docker run --log-driver json-file --log-opt max-size=10m --log-opt max-file=3 nginx
```

> [!WARNING]
> Если `max-size` и `max-file` не заданы явно, Docker не ограничивает размер логов. На хосте с множеством контейнеров это выльется в неожиданный дефицит места.

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

## Драйвер journald

`journald` отправляет логи контейнеров в системный журнал systemd. Это значит, что логи доступны через `journalctl`, поддерживаются все механизмы вращения и сжатия journald, и нет отдельных JSON-файлов, разрастающихся на диске.

Для работы нужен `systemd` и пакет `systemd-journal-remote` (в некоторых дистрибутивах). Контейнер должен запускаться с указанием драйвера:

```bash
docker run --log-driver journald --log-opt tag={{.Name}} nginx
```

Флаг `tag` задаёт идентификатор в journald — без него будет пустая строка, и найти нужный контейнер будет сложно. Шаблон `{{.Name}}` подставляет имя контейнера.

> [!TIP]
> Используйте `tag={{.Name}}` или `tag={{.ID}}`, чтобы логи из journald были сразу привязаны к конкретному контейнеру. Без тега фильтрация по `CONTAINER_NAME` не работает.

Чтение логов:

```bash
journalctl -u docker --grep="nginx"
journalctl --user-console -t docker --since "1 hour ago"
```

Точнее — через фильтры journald:

```bash
journalctl -t docker -g "nginx" --since "2024-01-01"
```

Реальная фильтрация зависит от того, какие метаданные Docker передаёт в journald. Проверьте `journalctl -o verbose` для конкретного контейнера, чтобы увидеть доступные поля.

## Сравнение json-file и journald

| Параметр | json-file | journald |
|---|---|---|
| Место хранения | `/var/lib/docker/containers/...` | `/var/log/journal/` |
| Вращение | Через `--log-opt` | Через `journald.conf` |
| Поиск | `docker logs --since`, `grep` | `journalctl --grep`, `--since` |
| Зависимости | Нет | systemd |
| Централизация | Через `fluentd`, `gelf`, `awslogs` | Через `journalctl --remote` или forward |
| Сжатие | Нет (ручное) | Да, настраивается в `journald.conf` |
| Доступ без Docker | Прямой доступ к файлам | Только через `journalctl` |

> [!WARNING]
> `journald` не поддерживает все `log-opt`, доступные для `json-file`. Например, `max-size` и `max-file` не работают — вращение контролируется настройками самого journald (`SystemMaxUse`, `SystemMaxFileSize` и т.д.).

## Настройка драйвера в daemon.json

Глобальная настройка делается в `/etc/docker/daemon.json`:

```json
{
  "log-driver": "journald",
  "log-opts": {
    "tag": "{{.Name}}"
  }
}
```

После изменения перезапустите Docker:

```bash
sudo systemctl restart docker
```

> [!NOTE]
> Изменение драйвера в `daemon.json` влияет на **все новые контейнеры**. Уже запущенные контейнеры продолжат использовать свой текущий драйвер до перезапуска.

Для контейнера можно переопределить через `--log-driver` и `--log-opt` при запуске — это имеет приоритет над настройками демона.

Если нужно проверить текущий драйвер конкретного контейнера:

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

## Практические рекомендации

Для локальной разработки `json-file` с заданными `max-size` и `max-file` — достаточен и прост в использовании. Для продакшена с десятками контейнеров на одном хосте `journald` предпочтительнее: единое пространство поиска, встроенное сжатие, интеграция с `systemd` и мониторингом.

> [!TIP]
> Если вы уже используете `systemd` для оркестрации контейнеров (через `systemd` unit-файлы или Podman), `journald` — естественный выбор. Логи контейнеров и сервисов окажутся в одном месте.

Если нужна централизованная сборка — оба драйвера поддерживают forward-логов через промежуточные драйверы (`fluentd`, `gelf`, `splunk`). Но `journald` добавляет дополнительный этап: сначала в journald, потом forwarder. Для простых случаев прямой `json-file` + `fluentd` может быть короче пути.

Проверяйте дисковое пространство регулярно, независимо от драйвера. `journalctl --disk-usage` и `du -sh /var/lib/docker/containers/*/` — минимальный набор для мониторинга.
