Docker и DevOps 13 мин чтения 2026-10-10

Реалтайм-мониторинг логов Docker-контейнеров в Dozzle: легкий веб-интерфейс, мгновенный поиск и изоляция сокетов без тяжелого стека ELK

Инструкция по развертыванию Dozzle в Docker Compose: легкий веб-интерфейс для мониторинга логов контейнеров, потребляющий всего 15 МБ RAM, с поиском по regex, защитой сокета и SSL.

Инженерная редакция SysKit Проверено инженерами SysKit.ru

В современной микросервисной архитектуре контейнеризация стала стандартом де-факто: даже на небольшом виртуальном сервере VDS обычно работают от 5 до 25 изолированных сервисов (веб-сервер, бэкенд, база данных, Redis, очереди задач, боты и воркеры). Когда в одном из приложений возникает непредвиденная ошибка, администратору или разработчику необходимо мгновенно локализовать причину в логах.

Однако стандартный подход к чтению логов через терминальную команду docker logs -f --tail 100 <container> быстро превращается в рутину: приходится постоянно подключаться по SSH, переключаться между окнами консоли и вручную прокручивать гигабайты текста. Развертывание же тяжелых систем централизованного сбора логов (Elasticsearch/Logstash/Kibana или Grafana Loki) требует от 1.5 до 4 ГБ оперативной памяти, что экономически нецелесообразно на компактных VDS за несколько сотен рублей.

Легковесный инструмент Dozzle решает эту задачу идеально: написанный на Go и Vue, он потребляет всего 10–15 МБ RAM в простое (до 20–25 МБ под активной нагрузкой), запускается в одну команду и сразу открывает реактивный веб-интерфейс с живым потоком логов всех контейнеров, поиском по регулярным выражениям и мониторингом потребления памяти и процессора. В актуальных релизах ветки Dozzle (включая современные версии v11.x) поддерживаются вход через OAuth/OIDC (GitHub, Google, Authentik), мультисерверный мониторинг нескольких VDS и сплит-экран.

1. Проблема отладки контейнеров: ограничения docker logs и избыточность ELK

Системные администраторы и разработчики при анализе событий в Docker обычно сталкиваются с двумя крайностями:

  1. Консольный CLI (docker logs):
    • Не позволяет комфортно отслеживать синхронные события в нескольких взаимосвязанных контейнерах (например, Nginx $ ightarrow$ PHP-FPM $ ightarrow$ MySQL).
    • Крайне неудобен при экстренной диагностике со смартфона или планшета вне рабочего места.
    • Отсутствует подсветка синтаксиса, кликабельная навигация и моментальная фильтрация по типам ошибок (ERROR / WARN / INFO).
  2. Тяжелые стеки сбора логов (ELK, OpenSearch, Grafana Loki):
    • Требуют выделенной базы данных, агентов сбора (Promtail, Filebeat) и индексации.
    • Потребляют значительные объемы CPU и оперативной памяти просто на поддержание фоновых индексов.
    • Избыточны, если вам не требуется хранить историю логов за последние 90 дней, а нужно лишь видеть текущее состояние сервисов прямо сейчас.

Сравним ключевые характеристики инструментов мониторинга логов:

Критерий Консоль docker logs Dozzle Стек ELK / Loki
Потребление RAM 0 МБ (встроен в демон) ~10–25 МБ (в зависимости от нагрузки) от 1.5 до 4+ ГБ
Интерфейс SSH / терминал Веб-интерфейс (SPA) Веб-дашборд (Kibana/Grafana)
Скорость старта Мгновенно 1–2 минуты От 30 минут до нескольких часов
Поиск и regex Только через grep Мгновенный живой поиск Полнотекстовый поиск с индексами

💡 Принцип работы Dozzle

Dozzle не создает собственных баз данных и не хранит логи на диске. Он напрямую подключается к локальному сокету /var/run/docker.sock и транслирует поток вывода контейнеров в браузер через легковесный протокол Server-Sent Events (SSE). Если закрыть вкладку в браузере, передача данных останавливается, а нагрузка на сервер падает до нуля.

2. Развертывание Dozzle в Docker Compose: манифест, сокет и лимиты ресурсов

Для надежного развертывания Dozzle создадим изолированную директорию на сервере и подготовим файл docker-compose.yml.

# Создаем рабочую папку проекта
mkdir -p /opt/dozzle && cd /opt/dozzle

Подготовим файл конфигурации /opt/dozzle/docker-compose.yml:

services:
  dozzle:
    image: amir20/dozzle:latest
    container_name: dozzle
    restart: unless-stopped
    ports:
      # ВНИМАНИЕ: привязка строго к 127.0.0.1 для защиты от обхода фаервола UFW
      - "127.0.0.1:8888:8080"
    volumes:
      # Проброс сокета в режиме read-only (:ro)
      - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      # Уровень логирования самого Dozzle
      - DOZZLE_LEVEL=info
      # Отключение сбора телеметрии
      - DOZZLE_NO_ANALYTICS=true
    # Нативные лимиты ресурсов для защиты сервера от OOM Killer (совместимо со всеми версиями Compose)
    mem_limit: 128m
    cpus: 0.50
    deploy:
      resources:
        limits:
          memory: 128M
          cpus: "0.50"

Обратите внимание на ключевые правила безопасности и архитектуры в манифесте:

  • Привязка порта к 127.0.0.1:8888: если указать просто 8888:8080, Docker автоматически создаст правила в iptables в обход системного фаервола UFW, и веб-панель станет доступна всему интернету без авторизации. Привязка к локальному лупбэку гарантирует, что доступ возможен только через защищенный реверс-прокси Nginx.
  • Ограничения сокета :ro: директива /var/run/docker.sock:/var/run/docker.sock:ro защищает сам файл сокета на диске от перезаписи и изменения прав. Однако протокол Docker API работает поверх HTTP REST, поэтому для абсолютной изоляции API-методов (полного запрета POST, PUT, DELETE) в высоконагруженных средах рекомендуется использовать промежуточный прокси docker-socket-proxy (подробно разобран в Разделе 6).
  • Двойная совместимость лимитов ресурсов: одновременное указание mem_limit и deploy.resources.limits гарантирует, что лимиты памяти в 128 МБ будут строго применены как в классическом режиме Compose Standalone на одиночном VDS, так и в окружениях Docker Swarm и Compose v2+.
# Запуск контейнера в фоновом режиме
docker compose up -d

# Проверка статуса службы
docker compose ps

3. Возможности веб-интерфейса: regex-фильтрация, мультискрин и метрики RAM/CPU

После развертывания Dozzle предоставляет удобный одностраничный веб-интерфейс (SPA), спроектированный с акцентом на скорость работы и эргономику.

Ключевые функциональные возможности дашборда:

  • Живой стриминг логов в реальном времени: новые строки появляются мгновенно без необходимости перезагрузки страницы благодаря Server-Sent Events (SSE).
  • Мгновенный поиск по регулярным выражениям: поисковая строка поддерживает синтаксис Regex (например, (error|fatal|exception)), позволяя отфильтровать миллион строк за доли секунды прямо на стороне браузера.
  • Режим разделения экрана (Split Screen): вы можете одновременно закрепить на одном экране вывод двух или трех взаимосвязанных контейнеров (например, веб-приложение, базу данных и фоновый воркер), сопоставляя время событий с точностью до миллисекунды.
  • Мини-мониторинг ресурсов контейнеров: рядом с именем каждого контейнера в режиме реального времени отображаются шкалы утилизации памяти (RAM) и процессора (CPU), позволяя сразу заметить утечку памяти или зависший процесс.
  • Скачивание и очистка: одной кнопкой можно скачать полный текстовый файл лога для последующего анализа или очистить текущее окно отображения.

💡 Горячие клавиши Dozzle

Для ускорения навигации в интерфейсе предусмотрены клавиатурные сочетания: клавиша / моментально переносит фокус в строку поиска, Ctrl + K открывает меню быстрого переключения между контейнерами, а Shift + F включает режим автоматической прокрутки к свежим записям (Autoscroll).

4. Публикация через Nginx Reverse Proxy и автоматический выпуск SSL-сертификата

Для безопасного доступа к интерфейсу через интернет настроим веб-сервер Nginx в качестве обратного прокси-сервера с защитой HTTPS.

Особенность работы Dozzle заключается в непрерывной трансляции потока логов через Server-Sent Events. Поэтому в конфигурации Nginx критически важно отключить буферизацию прокси (proxy_buffering off;), иначе строки логов будут задерживаться в буфере до его полного заполнения.

Создадим базовый виртуальный хост для подтверждения домена в файле /etc/nginx/sites-available/dozzle.conf:

server {
    listen 80;
    server_name logs.example.com;

    location / {
        proxy_pass http://127.0.0.1:8888;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # Критически важно для стриминга логов SSE и WebSocket
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_buffering off;
        proxy_cache off;
        chunked_transfer_encoding on;
    }
}

Активируем сайт и проверим синтаксис конфигурации:

# Создаем символическую ссылку
sudo ln -s /etc/nginx/sites-available/dozzle.conf /etc/nginx/sites-enabled/

# Тестируем конфигурацию и перезагружаем Nginx
sudo nginx -t && sudo systemctl reload nginx

Теперь выпустим бесплатный SSL-сертификат Let's Encrypt с автоматической настройкой HTTPS и перенаправления с HTTP:

# Выпуск сертификата через Certbot с обязательным флагом автоматического редиректа
sudo certbot --nginx -d logs.example.com --non-interactive --agree-tos -m admin@example.com --redirect

Утилита Certbot автоматически дополнит виртуальный хост директивами SSL и создаст безопасный постоянный 301-редирект на защищенный протокол HTTPS.

5. Требования к ресурсам: почему Dozzle идеален для серверов от 1 ГБ RAM

В отличие от тяжелых систем сбора логов, Dozzle не создает фоновых баз данных, не индексирует дисковые разделы и не держит постоянных пулов памяти под Java Virtual Machine.

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

Параметр Потребление Dozzle Влияние на виртуальный сервер (VDS)
Оперативная память (RAM) 10–15 МБ в простое (< 25 МБ под нагрузкой) Оставляет практически 100% оперативной памяти для полезной нагрузки ваших рабочих приложений и СУБД.
Процессор (CPU) < 0.1% в простое Не нагружает процессор фоновыми задачами; всплеск до 1–2% возникает только в момент активного поиска по длинным логам.
Дисковое пространство ~7–10 МБ (сжатый) / ~35 МБ (на диске) Скомпилированный бинарный образ Dozzle на базе Scratch занимает считанные мегабайты и не засоряет NVMe-накопитель.

Для стабильной работы стека с несколькими рабочими контейнерами (например, сайт на WordPress/Laravel + база данных MySQL + Nginx + Dozzle) достаточно базового VDS с 1–2 vCPU и 1–2 ГБ RAM. Это делает решение максимально доступным для персональных проектов и небольших IT-компаний.

Рекомендуемые VDS-провайдеры

Отказоустойчивые сервера с быстрыми NVMe и каналом до 1 Гбит/с

Выбор редакции
⚡

Timeweb Cloud — Быстрые NVMe VDS для Docker

Идеальная среда для запуска микросервисов: быстрые NVMe-диски, мгновенный деплой Ubuntu и стабильный порт 1 Гбит/с.

Конфигурация
1 vCPU 3.3+ ГГц • 1 ГБ RAM • 15 ГБ NVMe • Трафик без лимита
Премиум Tier III
🔷

Selectel — Надежные облачные серверы Tier III

Корпоративная облачная инфраструктура с гарантированными ресурсами CPU и приватными сетями для кластеров контейнеров.

Конфигурация
2 vCPU • 2 ГБ RAM • 30 ГБ NVMe • Дата-центры Tier III
Простота и стабильность
🟠

Beget — Простота управления и автоматические бэкапы

Удобная панель управления сервером, готовый стек Docker в 1 клик, ежедневные бесплатные резервные копии и поддержка 24/7.

Конфигурация
1 vCPU • 1 ГБ RAM • 15 ГБ NVMe • Бесплатные бэкапы

6. Безопасность и контроль доступа: встроенная авторизация и изоляция docker.sock

Поскольку логи приложений могут содержать конфиденциальные данные (переменные окружения, токены сессий, IP-адреса клиентов и стек-трейсы ошибок с параметрами SQL-запросов), открывать веб-интерфейс Dozzle без аутентификации категорически недопустимо.

В современных версиях Dozzle предусмотрено два уровня защиты:

1. Встроенная авторизация пользователей (Simple Auth с bcrypt-хешированием)

Dozzle поддерживает встроенный механизм авторизации через файл users.yml. Критическое требование безопасности: Dozzle не принимает открытые пароли — каждый пароль обязан храниться исключительно в виде надежного bcrypt-хеша. Хранение пароля в открытом виде (plaintext) не поддерживается и создает прямую уязвимость.

Сгенерировать безопасный пароль и его bcrypt-хеш можно с помощью утилиты Генератор безопасных паролей и одноразового контейнера Apache htpasswd:

# Генерация bcrypt-хеша для пользователя admin через временный контейнер
docker run --rm httpd:alpine htpasswd -nbB admin "ВашНадежныйПароль"

Команда выведет строку формата admin:$2y$05$.... Скопируйте полученный хеш в файл конфигурации учетных записей /opt/dozzle/data/users.yml:

# /opt/dozzle/data/users.yml
users:
  - username: admin
    # Пароль обязан храниться строго в виде bcrypt-хеша!
    password: "$2y$05$9ho4vY2LdJ/WBopFcsAS0uORC0x2vuFHQgT/yBqZyzclhHsoaIkzK"
    name: "Системный администратор"
    email: admin@example.com

Зададим строгие права доступа к файлу с хешами, чтобы исключить его чтение непривилегированными пользователями операционной системы:

# Ограничиваем права на чтение только владельцем
chmod 600 /opt/dozzle/data/users.yml

В манифесте docker-compose.yml смонтируем директорию с данными и активируем встроенную авторизацию:

    environment:
      - DOZZLE_LEVEL=info
      - DOZZLE_NO_ANALYTICS=true
      - DOZZLE_AUTH_PROVIDER=simple
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./data:/data

⚠️ Продвинутая аутентификация в Dozzle v11+

В современных версиях Dozzle помимо Simple Auth поддерживается корпоративная интеграция через провайдеры OAuth2/OIDC (GitHub, Google, Authentik, Keycloak) через переменные DOZZLE_AUTH_PROVIDER=forward-proxy или прямое подключение OIDC-клиента, что позволяет использовать единый вход (SSO) и двухфакторную аутентификацию (2FA).

2. Повышенная изоляция через docker-socket-proxy

Если вы хотите полностью исключить прямое монтирование системного сокета /var/run/docker.sock в пользовательский контейнер, можно использовать промежуточный легковесный прокси tecnativa/docker-socket-proxy на базе HAProxy. Он блокирует любые модифицирующие методы Docker API (POST, DELETE, PUT), разрешая исключительно чтение списков контейнеров и логов:

services:
  socket-proxy:
    image: tecnativa/docker-socket-proxy:latest
    container_name: docker-socket-proxy
    restart: unless-stopped
    mem_limit: 64m
    cpus: 0.25
    deploy:
      resources:
        limits:
          memory: 64M
          cpus: "0.25"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      # Разрешаем только чтение информации о контейнерах
      - CONTAINERS=1
      - EVENTS=1
      - LOG_LEVEL=warning
      # Полный запрет на любые изменения и управление
      - POST=0
      - DELETE=0
      - PUT=0

  dozzle:
    image: amir20/dozzle:latest
    container_name: dozzle
    restart: unless-stopped
    depends_on:
      - socket-proxy
    ports:
      - "127.0.0.1:8888:8080"
    environment:
      - DOCKER_HOST=tcp://socket-proxy:2375
      - DOZZLE_NO_ANALYTICS=true
    mem_limit: 128m
    cpus: 0.50
    deploy:
      resources:
        limits:
          memory: 128M
          cpus: "0.50"

💡 Преимущество socket-proxy

При использовании docker-socket-proxy контейнер Dozzle физически не имеет доступа к сокету на хосте. Даже в гипотетическом сценарии уязвимости в коде сервиса злоумышленник не сможет выполнить команду выхода из контейнера (container breakout) на хостовую операционную систему.

7. Мониторинг нескольких серверов: подключение удаленных VDS через Dozzle Agent

Если ваша инфраструктура состоит из нескольких серверов VDS (например, веб-сервер, отдельный сервер баз данных и staging-стенд), Dozzle позволяет централизованно отслеживать логи всех нод в едином интерфейсе без необходимости открывать разные вкладки.

Для этого на удаленном сервере запускается легковесный агент Dozzle:

# Запуск агента на удаленном VDS (привязка строго к локальному адресу или VPN-интерфейсу)
docker run -d \
  --name dozzle-agent \
  --restart unless-stopped \
  -v /var/run/docker.sock:/var/run/docker.sock:ro \
  -p 127.0.0.1:7007:7007 \
  amir20/dozzle:latest agent

⚠️ Важное предупреждение по безопасности сетевого агента

Протокол tcp:// в Dozzle Agent передает данные в открытом виде без встроенного TLS-шифрования. Категорически запрещено пробрасывать порт 7007 в публичный интернет через внешние IP-адреса! Передача данных между серверами должна осуществляться строго внутри шифрованного VPN-контура (WireGuard, Tailscale на приватных адресах 10.x.x.x) либо через SSH-туннель с привязкой к 127.0.0.1.

На главном сервере в основном дашборде Dozzle удаленный хост подключается через переменную DOZZLE_REMOTE_HOST с указанием внутреннего VPN-адреса:

    environment:
      # Подключение через приватную защищенную сеть WireGuard/Tailscale
      - DOZZLE_REMOTE_HOST=tcp://10.10.0.2:7007,tcp://10.10.0.3:7007

В результате в боковой панели интерфейса появится выпадающий список со всеми подключенными серверами, позволяя моментально переключаться между VDS без повторной авторизации.

8. Итоговый чек-лист сисадмина по безопасной настройке мониторинга логов

Перед вводом панели мониторинга в промышленную эксплуатацию выполните последовательную проверку по чек-листу:

📋 Чек-лист безопасности и надежности Dozzle

  • Порт контейнера привязан строго к локальному интерфейсу 127.0.0.1:8888 (исключен обход UFW).
  • Проверен статус сетевых портов через онлайн-инструмент Сканер портов онлайн: внешний доступ к порту 8888 заблокирован.
  • Сокет /var/run/docker.sock смонтирован строго с флагом :ro (только для чтения) либо изолирован через docker-socket-proxy.
  • В docker-compose.yml заданы лимиты памяти (mem_limit: 128m и deploy.resources.limits) для защиты от OOM Killer.
  • Пароли в users.yml надежно захэшированы с использованием алгоритма bcrypt (хранение в открытом виде исключено).
  • Установлены строгие права доступа chmod 600 на файл users.yml.
  • В Nginx отключена буферизация прокси через директивы proxy_buffering off; и proxy_cache off; для мгновенного SSE-стриминга.
  • Выпущен валидный SSL-сертификат Let's Encrypt и проверен через Проверка SSL / TLS сертификата.
  • При мониторинге удаленных VDS порт агента 7007 изолирован внутри защищенного VPN-туннеля (WireGuard/Tailscale).
  • Отключена отправка телеметрии директивой DOZZLE_NO_ANALYTICS=true.

Разверните удобную среду для Docker на быстром VDS

Запустите контейнеры и легкий мониторинг на скоростных облачных серверах с быстрыми NVMe-дисками и каналом 1 Гбит/с у ведущих провайдеров.

Вопросы и ответы (FAQ)

Популярные вопросы вебмастеров и сисадминов по данной теме

Чем Dozzle отличается от Portainer или стека Grafana Loki?
Portainer — это полноценная панель управления жизненным циклом контейнеров (деплой, сети, тома), а Grafana Loki — мощная база данных логов с долгосрочным хранилищем. Dozzle сфокусирован исключительно на одной задаче: мгновенном реалтайм-просмотре, фильтрации и поиске логов запущенных контейнеров без индексов, баз данных и расхода дискового пространства.
Безопасно ли монтировать /var/run/docker.sock в контейнер Dozzle?
При прямом монтировании сокета обязательно указывайте флаг только для чтения (:ro). Для максимального уровня безопасности в промышленном окружении рекомендуется использовать промежуточный прокси tecnativa/docker-socket-proxy, блокирующий любые POST, PUT и DELETE запросы к Docker API.
Сколько оперативной памяти и процессорного времени потребляет Dozzle?
Благодаря реализации на скомпилированном языке Go и эффективному стримингу Server-Sent Events (SSE), сервис потребляет всего 10–15 МБ оперативной памяти в простое (до 20–25 МБ при активной фильтрации) и практически 0% CPU в режиме ожидания, что делает его пригодным даже для минимальных VDS с 512 МБ – 1 ГБ RAM.
Почему пароль в файле users.yml обязательно должен храниться в виде bcrypt-хеша?
Встроенный механизм Simple Auth в Dozzle не поддерживает пароли в открытом виде (plaintext) в целях безопасности. В конфигурации users.yml каждый пароль обязан быть зашифрован в формате bcrypt (например, через команду docker run --rm httpd:alpine htpasswd -nbB admin пароль). Это исключает компрометацию учетной записи даже при случайном чтении конфигурационного файла.

Читайте также в блоге SysKit

Смежные руководства и полезные технические статьи