DigraphDocs Docker Infrastructure Graph

Docs / Архитектура

Портал и контуры

Портал обслуживает людей и карту инфраструктуры. Контур живёт рядом с Docker-хостом и владеет его данными. Портал никогда не ходит в Docker, контур никогда не знает о других контурах.

Два слоя

ПорталКонтур
РольВход, инвентарь, проксиDocker-хост и его данные
БДportal_data: контуры, серверы, зашифрованные токеныsqlite_data: история, метрики, секреты, настройки
ВходOIDC SSO или токен портала; свои JWT-сессииТолько AUTH_TOKEN
API/api/portal/* + прокси /api/remote/{id}/*/api/*: граф, действия, настройки
Ключ AI / SSOХранит и используетНе участвует в режиме портала
Веб-серверОтдаёт UI и статикуМожет отдавать UI в standalone

Компоненты контура

СервисРольСеть / доступ
docker-statВеб-приложение: сбор, история, UI, APIfrontend, backend, control, telemetry
docker-apiТипизированный /v1 и allow-list Docker API; держит сокетbackend
compose-runnerup/down/restart/pull с сокетомcontrol
volume-scannerДеревья томов через /var/lib/docker/volumes:robackend
vuln-scannerTrivy-сканирование образов через docker-apibackend + egress за базой
metrics-agentМетрики хоста из /proctelemetry

Сеть backend внутренняя (internal: true), как и control и telemetry; наружу смотрит только frontend (портал, AI-провайдер, egress сканера).

Все сервисы публикуются как образы hub.docker-infra.ru/digraph/<service>:<version>; контур и портал ставятся из deploy/contour и deploy/portal.

Docker-агент

Веб-процесс не монтирует docker.sock и не говорит на Docker HTTP API. Единственный держатель сокета — docker-api, у него две поверхности:

  • типизированный /v1/… — список, inspect, stats, logs, lifecycle, exec по WebSocket, сети, тома, образы, поток событий;
  • allow-list raw-путей Docker API — только для volume-scanner и vuln-scanner.

Обе поверхности используют одну политику PRIVILEGES и один кольцевой аудит. Агент вырезает значения Config.Env, не-compose labels и креденшелы из истории слоёв до отправки ответа.

Маршрутизация

Браузер обращается только к порталу; по префиксу пути портал решает, что делать.

Путь в браузереКуда уходитКто проверяет доступ
/, /assets/…, /config.jsстатика порталапублично
/api/portal/auth/*, /api/portal/healthпорталпублично, кроме login
/api/portal/settings, /inventory, /contours, /serversБД порталаJWT портала
/api/portal/ai/*AI-провайдер порталаJWT портала
/api/remote/{id}/api/…контур http://host:port/api/…JWT портала, затем AUTH_TOKEN контура

Два разных 401

Ответ 401 может означать две разные вещи:

  • истёк или отсутствует JWT портала — UI обновит сессию по refresh-токену;
  • контур не принял сохранённый токен — это не проблема сессии портала.

Чтобы браузер не разлогинивал пользователя из-за чужого ключа, прокси переписывает 401 контура в 502 {"code":"contour_unauthorized"}. Такой ответ означает: откройте сервер в /#/dashboard и введите ключ заново (двойной клик по ноде).

Что где настраивается

НастройкаПорталКонтур
Вход пользователя: OIDC или токен портала●—
Контуры, серверы и токены контуров●—
AI-провайдер: URL, модель, язык, ключ● выполняет— в режиме портала
Интервал сбора и retention истории/метрик—●
Разделы events/projects/secrets/security—●
PRIVILEGES—● только env
Проекты, секреты, бэкапы, сканер уязвимостей—●
Алерты контура и их вебхуки—●
Доступность контуров и каналы дежурства●—

Страницы: /#/settings — настройки портала; /#/contour — настройки выбранного контура (меню → Host → Config).

AI и SSO принадлежат порталу

Ключ AI шифруется SECRET_MASTER_KEY портала, никогда не уходит в браузер (только факт api_key_set) и не копируется в контуры. UI вызывает /api/portal/ai/*; портал собирает prompt из контекста, который прислал интерфейс, и сам стримит ответ провайдера. Заключения хранятся в БД портала и привязаны к server_id.

SSO — тоже relying party портала: issuer, client ID, secret, redirect и allowlist хранятся в portal_settings, secret зашифрован. Контур в режиме портала принимает только токен.

Хранение

  • SQLite с WAL и одной writer-сессией; история пишется только при изменении графа.
  • Отдельная таймсерия метрик хоста с собственной ретенцией и предохранителями по строкам.
  • Срезы хранят хвост логов каждого контейнера — исторические логи доступны после compose down.
  • Портал хранит только инвентарь, настройки, сессии и заключения AI.