MAATRIX / Блог / Observium в Docker Compose: готовый файл

Observium в Docker Compose: готовый файл

MAATRIX

Если у вас в сети десяток свитчей, пара роутеров и стойка серверов с SNMP-агентами, руками сводить их состояние в одну картину — трата времени. Observium умеет находить устройства по SNMP, опрашивать их и рисовать графики трафика, загрузки CPU и показаний температурных датчиков без танцев с бубном вокруг конфигов. Официального Docker-образа у проекта нет, поэтому ниже — рабочий docker-compose.yml на основе собственного Dockerfile, который можно сразу поднять на сервере.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Что такое Observium и зачем ему автообнаружение по SNMP

Observium — платформа мониторинга сети, написанная в 2009 году как более простая альтернатива Cacti и Nagios. В 2013-м от неё отпочковался LibreNMS — открытый форк с более активной разработкой, но ядро логики (RRDtool-графики, SNMP-поллер, веб на PHP) у обоих продуктов общее, и многое из этой статьи применимо и к нему.

Ключевая фишка Observium — не просто опрос по списку IP, а обнаружение соседей через CDP, LLDP и FDP. Вы добавляете один узел вручную, а дальше система читает у него таблицу соседства по SNMP, находит подключённые свитчи и роутеры и предлагает добавить их тоже. Для сети из десятков L2/L3-устройств это экономит часы ручной инвентаризации.

Есть нюанс с редакциями:

ПараметрCommunity (бесплатно)Professional / Enterprise
Цена0платная подписка по числу устройств
Источник обновленийпубличный SVN-репозиторий, обновляется режеприватный репозиторий, регулярные релизы
Скан подсети целикомнет, только добавление узла + discovery соседейесть, скан диапазона IP
Поддержкафорум сообществаприоритетная от разработчиков

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

Архитектура стека в Docker Compose

Официальный Observium ставится на голое железо через SVN-checkout и системный cron — так исторически написана документация проекта, и это плохо ложится на один контейнер с процессом на переднем плане. Поэтому стек собираем из четырёх частей:

  • db — MariaDB, хранит инвентарь устройств, пороги, пользователей и метаданные графиков;
  • observium-web — nginx + php-fpm, отдаёт веб-интерфейс;
  • observium-poller — тот же образ, но вместо веб-сервера крутит цикл опроса уже добавленных устройств каждые 5 минут;
  • observium-discovery — отдельный процесс автообнаружения новых соседей по SNMP, запускается реже поллера.

Все три сервиса собираются из одного Dockerfile и делят два volume: под RRD-графики (чистый I/O, лучше сразу класть на быстрый диск) и под логи.

observium/
├── docker-compose.yml
├── .env
├── Dockerfile
├── entrypoint.sh
├── config.php
└── nginx.conf

Разделение поллера и discovery — сознательное решение: полный обход сети в поисках новых соседей занимает дольше, чем пятиминутный интервал опроса уже известных устройств, и не должен тормозить свежие графики.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Dockerfile и entrypoint: собираем образ без готового пакета

Debian 12 (bookworm) несёт в базовых репозиториях PHP 8.2 и всё нужное для SNMP и RRDtool, так что своя сборка занимает один слой:

FROM debian:12-slim
ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y \
    subversion cron nginx \
    php8.2-fpm php8.2-cli php8.2-mysqli php8.2-gd \
    php8.2-curl php8.2-snmp php8.2-xml php8.2-mbstring php8.2-zip \
    rrdtool snmp snmp-mibs-downloader \
    fping mtr-tiny nmap ipmitool graphviz imagemagick whois \
    python3 python3-pymysql mariadb-client \
    && rm -rf /var/lib/apt/lists/*

# Debian по умолчанию отключает загруженные MIB-ы — включаем
RUN sed -i 's/^mibs :/# mibs :/' /etc/snmp/snmp.conf

RUN svn checkout http://svn.observium.org/svn/observium/trunk /opt/observium

WORKDIR /opt/observium
RUN mkdir -p rrd logs && chown -R www-data:www-data /opt/observium

COPY nginx.conf /etc/nginx/sites-available/default
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

EXPOSE 80
ENTRYPOINT ["/entrypoint.sh"]

Строка с sed закрывает частую граблю: без неё snmpwalk отдаёт голые OID вместо человекочитаемых имён, и графики в интерфейсе подписаны нечитаемым набором цифр.

entrypoint.sh ждёт базу, при первом старте накатывает схему и дальше либо поднимает веб, либо уходит в цикл поллинга или discovery — в зависимости от аргумента команды:

#!/bin/bash
set -e

until mysqladmin ping -h"$DB_HOST" -u"$DB_USER" -p"$DB_PASS" --silent; do
  echo "Ждём базу данных..."
  sleep 3
done

if [ ! -f /opt/observium/.initialized ]; then
  php /opt/observium/discovery.php -u || true
  touch /opt/observium/.initialized
fi

case "$1" in
  web)
    service php8.2-fpm start
    exec nginx -g "daemon off;"
    ;;
  poller)
    while true; do
      python3 /opt/observium/poller-wrapper.py 4
      sleep 300
    done
    ;;
  discovery-cron)
    while true; do
      sleep 21600
      php /opt/observium/discovery.php -h all
    done
    ;;
esac

Команда discovery.php -u — часть штатной установочной процедуры Observium, но имя скрипта между версиями иногда меняется, так что перед боевым запуском сверьтесь с cat /opt/observium/INSTALL внутри контейнера.

config.php и docker-compose.yml целиком

Конфиг подключается volume-ом как read-only — так проще версионировать его отдельно от кода:

<?php
$config['db_extension'] = 'mysqli';
$config['db_host']      = getenv('DB_HOST') ?: 'db';
$config['db_user']      = getenv('DB_USER') ?: 'observium';
$config['db_pass']      = getenv('DB_PASS') ?: '';
$config['db_name']      = 'observium';

$config['rrd_dir'] = '/opt/observium/rrd';
$config['rrdtool'] = 'rrdtool';
$config['mibdir']  = '/opt/observium/mibs';
$config['own_hostname'] = 'observium.local';

// SNMP-community, которые Observium пробует при добавлении устройства
$config['snmp']['community'] = array('public');

// Автообнаружение соседей по протоколам L2
$config['discovery_modules']['cdp']  = 1;
$config['discovery_modules']['lldp'] = 1;
$config['discovery_modules']['fdp']  = 1;

$config['poller_modules']['ipmi'] = 0; // грузит поллер сильнее, чем нужно большинству
$config['auth_mechanism'] = 'mysql';

Полный набор ключей и модулей смотрите в config.php.default внутри чекаута — здесь только то, что нужно для старта. nginx.conf — стандартный php-fpm-прокси на сокет /run/php/php8.2-fpm.sock с корнем /opt/observium/html.

Сам docker-compose.yml:

services:
  db:
    image: mariadb:10.11
    restart: unless-stopped
    environment:
      MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
      MARIADB_DATABASE: observium
      MARIADB_USER: observium
      MARIADB_PASSWORD: ${DB_PASSWORD}
    volumes:
      - db_data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      interval: 10s
      timeout: 5s
      retries: 5

  observium-web:
    build: .
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
    environment:
      DB_HOST: db
      DB_USER: observium
      DB_PASS: ${DB_PASSWORD}
    volumes:
      - observium_rrd:/opt/observium/rrd
      - observium_logs:/opt/observium/logs
      - ./config.php:/opt/observium/config.php:ro
    ports:
      - "8087:80"
    command: web

  observium-poller:
    build: .
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
    environment:
      DB_HOST: db
      DB_USER: observium
      DB_PASS: ${DB_PASSWORD}
    volumes:
      - observium_rrd:/opt/observium/rrd
      - observium_logs:/opt/observium/logs
      - ./config.php:/opt/observium/config.php:ro
    command: poller

  observium-discovery:
    build: .
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
    environment:
      DB_HOST: db
      DB_USER: observium
      DB_PASS: ${DB_PASSWORD}
    volumes:
      - observium_rrd:/opt/observium/rrd
      - observium_logs:/opt/observium/logs
      - ./config.php:/opt/observium/config.php:ro
    command: discovery-cron

volumes:
  db_data:
  observium_rrd:
  observium_logs:

.env рядом с compose-файлом:

DB_ROOT_PASSWORD=замените_на_свой_пароль
DB_PASSWORD=замените_на_другой_пароль

Поднимаем стек: docker compose up -d --build.

Первый запуск: пользователь, устройство, автообнаружение

Веб-интерфейс без пользователя бесполезен — заводим админа скриптом из поставки Observium:

docker compose exec observium-web php /opt/observium/adduser.php admin 'СложныйПароль123' 10

Добавляем первое устройство — например, свитч с SNMP v2c и community public:

docker compose exec observium-web php /opt/observium/add_device.php 10.10.0.1 public v2c

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

docker compose exec observium-web php /opt/observium/discovery.php -h all

Если у добавленного свитча включён CDP или LLDP и SNMP-агент отдаёт таблицу соседей, следующий цикл observium-discovery (по умолчанию раз в 6 часов в нашей схеме) сам предложит подключённые устройства — их останется подтвердить в веб-интерфейсе в разделе Discovery.

Со стороны хоста, который вы мониторите, нужен минимально настроенный SNMP-агент. Пример для Linux (/etc/snmp/snmpd.conf):

rocommunity public 10.10.0.0/24
syslocation "DC1, стойка 4"
syscontact admin@example.com

После правки конфига агент перезапускается (systemctl restart snmpd), и устройство становится видимым для Observium в пределах указанной подсети. Про сам Docker Compose на сервере — с нуля и с типовыми граблями — мы отдельно писали в статье про пошаговую установку Docker Compose на Ubuntu 24.04.

Ресурсы, бэкап и когда переходить на LibreNMS

RRDtool пишет на диск при каждом цикле опроса каждого устройства — это много мелких random-write операций. Для пары десятков узлов хватит обычного SSD и 2 vCPU / 4 GB RAM на весь стек с запасом. Когда счёт устройств переваливает за сотню, узким местом почти всегда становится не CPU, а диск под /opt/observium/rrd — вынесите этот volume на NVMe отдельно от базы данных.

База и RRD-файлы — два независимых источника правды: без базы вы теряете инвентарь устройств и настройки, без RRD — историю графиков (сами устройства переоткроются заново). Бэкапить нужно оба:

docker compose exec db mariadb-dump -u observium -p observium > observium_db_$(date +%F).sql
docker run --rm -v observium_observium_rrd:/rrd -v $(pwd):/backup alpine \
  tar czf /backup/observium_rrd_$(date +%F).tar.gz -C /rrd .

Обновление до свежей версии Community — это svn update внутри чекаута, поэтому проще пересобрать образ без кеша: docker compose build --no-cache && docker compose up -d. Перед этим делайте дамп базы — SVN-репозиторий community-редакции обновляется без чёткого релизного цикла, и между чекаутами иногда меняется схема БД.

Если сеть заметно больше и Observium начинает упираться в производительность RRDtool и однопоточность части своих скриптов, логичная альтернатива — LibreNMS: тот же принцип автообнаружения по SNMP и CDP/LLDP, но более активная разработка и проще масштабирование. Мы разбирали его установку в статье про LibreNMS на VPS, а вопрос ресурсов — отдельно, в материале сколько RAM нужно для LibreNMS. Если задача шире, чем сетевые устройства — метрики приложений, алертинг, дашборды — стоит посмотреть в сторону Prometheus/Grafana или Zabbix; мы сравнивали подходы в статье Zabbix или Prometheus — что выбрать для сервера.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Нужен ли официальный Docker-образ Observium?

Нет, проект его не публикует. Сборка из SVN-чекаута — единственный путь, если не покупать Professional-редакцию с иной поставкой.

Почему на графиках подписи вида .1.3.6.1.2.1.2.2.1.2 вместо имён интерфейсов?

MIB-файлы не подключены. Проверьте, что строка mibs : в /etc/snmp/snmp.conf закомментирована и что snmp-mibs-downloader реально установился — иногда сборка требует принять лицензию.

Можно ли просканировать всю подсеть автоматически?

В Community — нет: добавляете первое устройство вручную, дальше работает discovery соседей по CDP/LLDP/FDP. Скан подсети целиком — функция платных редакций.

Что делать, если устройство не находится?

Проверьте SNMP с сервера: docker compose exec observium-web snmpwalk -v2c -c public 10.10.0.1 system. Нет ответа — проблема в ACL устройства или в файрволе между контейнером и сетью мониторинга.

Почему MariaDB, а не PostgreSQL?

Observium исторически заточен под MySQL/MariaDB, поддержки PostgreSQL в нём нет.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →