Gatus в Docker Compose: готовый файл
Uptime Kuma удобен, пока вы не захотели хранить конфигурацию мониторинга в git и поднимать её одной командой на новом сервере — у него всё в SQLite, клики мышью и никакого «конфиг как код». Gatus решает именно эту задачу: один YAML-файл описывает все проверки, статус-страницу и алерты, а сам сервис — это один статический бинарник на Go без базы данных по умолчанию. Ниже — рабочий docker-compose.yml и config.yaml, которые можно скопировать и адаптировать под свои сервисы.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Что такое Gatus и когда он лучше Uptime Kuma
Gatus — это монитор доступности с открытым кодом (twinproduction/gatus), который периодически ходит на ваши эндпоинты (HTTP, TCP, DNS, ICMP, WebSocket, произвольные команды) и проверяет ответ на набор условий. Результат — статус-страница в духе тех, что публикуют облачные провайдеры после инцидентов, плюс алерты и экспорт метрик в Prometheus.
Ключевое отличие от Uptime Kuma — подход к хранению состояния. Gatus по умолчанию держит историю проверок в памяти и опционально пишет её в SQLite или PostgreSQL, но сама конфигурация — кто и как проверяется — всегда живёт в текстовом файле. Это значит:
- конфиг можно положить в git и ревьюить пул-реквестом;
- сервис поднимается на новом сервере воспроизводимо —
docker compose up -d, и всё уже настроено; - нет веб-интерфейса для редактирования проверок — только для просмотра статус-страницы;
- изменения конфигурации требуют перезапуска контейнера (или
docker compose restart, это доли секунды).
Если вам нужен инструмент для команды, где кто-то кликает мышкой в браузере, посмотрите Uptime Kuma — там ниже порог входа. Если мониторинг — часть инфраструктуры как кода, а не отдельная админ-панель, Gatus вписывается органичнее.
Готовый docker-compose.yml
Минимальная и при этом production-пригодная конфигурация — контейнер Gatus плюс том для конфига и том для данных (история проверок и метрики между рестартами):
services:
gatus:
image: twinproduction/gatus:latest
container_name: gatus
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- ./config:/config
- gatus-data:/data
environment:
- GATUS_CONFIG_PATH=/config
- TZ=Europe/Moscow
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost:8080/health"]
interval: 30s
timeout: 5s
retries: 3
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
volumes:
gatus-data:
Тег latest удобен для быстрого старта, но для продакшена зафиксируйте конкретную версию — посмотрите актуальные теги на Docker Hub и пропишите вместо latest что-то вроде v5.x.x, чтобы обновление образа не прилетало незаметно вместе с docker compose pull.
GATUS_CONFIG_PATH указывает Gatus искать все .yaml/.yml файлы в каталоге /config — так можно разбить конфигурацию на несколько файлов (например, endpoints.yaml, alerting.yaml) вместо одного большого. Создайте структуру рядом с compose-файлом:
gatus/
├── docker-compose.yml
└── config/
└── config.yaml
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверКонфигурация config.yaml: эндпоинты и условия
Базовый файл config/config.yaml с несколькими проверками разных типов:
storage:
type: sqlite
path: /data/data.db
endpoints:
- name: main-site
group: web
url: "https://example.com"
interval: 60s
conditions:
- "[STATUS] == 200"
- "[RESPONSE_TIME] < 500"
- "[CERTIFICATE_EXPIRATION] > 168h"
- name: api
group: web
url: "https://api.example.com/health"
interval: 30s
conditions:
- "[STATUS] == 200"
- "[BODY].status == healthy"
- name: postgres-tcp
group: infra
url: "tcp://db.example.com:5432"
interval: 60s
conditions:
- "[CONNECTED] == true"
- name: dns-resolve
group: infra
url: "8.8.8.8"
dns:
query-name: "example.com"
query-type: "A"
interval: 300s
conditions:
- "[DNS_RCODE] == NOERROR"
Условия (conditions) — сердце Gatus. Плейсхолдеры [STATUS], [RESPONSE_TIME], [BODY], [CERTIFICATE_EXPIRATION], [CONNECTED], [IP] подставляются из результата проверки, а [BODY].field позволяет заглядывать в JSON-ответ через точечную нотацию — удобно для health-эндпоинтов, которые отдают {"status": "healthy"}. Эндпоинт считается «упавшим», если провалилось хотя бы одно условие; на статус-странице он тут же переключается на красный.
Группировка через group — это не просто эстетика: на статус-странице эндпоинты сворачиваются по группам, и для инфраструктуры из десятка сервисов это заметно облегчает чтение.
Интервал (interval) стоит подбирать осознанно: 30 секунд для критичного API — разумно, но 60 проверок в минуту на бесплатном тарифе внешнего сервиса могут упереться в rate limit. Для внутренних сервисов, к которым Gatus стучится в той же docker-сети, это не проблема.
Статус-страница: настройка и кастомизация
По умолчанию статус-страница доступна на http://<host>:8080 и показывает список эндпоинтов с историей за последние сутки в виде полосок (зелёная — успех, красная — сбой). Кастомизация — тоже через YAML, добавьте секцию ui в конфиг:
ui:
title: "Статус сервисов — maatrix.io"
description: "Актуальное состояние наших сервисов в реальном времени"
header: "Статус maatrix.io"
logo: "https://example.com/logo.png"
link: "https://maatrix.io"
buttons:
- name: "Поддержка"
link: "https://maatrix.io/support"
dark-mode: true
Если нужна не публичная страница, а внутренний дашборд, самый простой вариант — не открывать порт 8080 наружу вовсе (убрать секцию ports из compose-файла) и заходить через VPN или SSH-туннель: ssh -L 8080:localhost:8080 user@server. Для команды, которой нужен доступ из офиса без VPN, вынесите Gatus за Traefik как reverse proxy с basic-auth или списком разрешённых IP — сам Gatus встроенной авторизации не предоставляет.
Уведомления: Telegram, Slack, Discord и другие
Алерты настраиваются в две части: глобальный блок alerting с учётными данными интеграции и список alerts внутри каждого эндпоинта — какие каналы использовать именно для него.
alerting:
telegram:
token: "123456789:AAExampleBotTokenHere"
id: "-1001234567890"
slack:
webhook-url: "https://hooks.slack.com/services/XXX/YYY/ZZZ"
endpoints:
- name: api
url: "https://api.example.com/health"
interval: 30s
conditions:
- "[STATUS] == 200"
alerts:
- type: telegram
failure-threshold: 3
success-threshold: 2
send-on-resolved: true
description: "API недоступен"
failure-threshold: 3 означает, что алерт уйдёт только после трёх подряд неудачных проверок — это отсекает разовые сетевые всплески и не превращает Telegram в поток ложных тревог. success-threshold: 2 — симметрично, для уведомления «сервис снова жив» нужно два подряд успеха. send-on-resolved: true включает именно это уведомление о восстановлении — без него вы узнаете о падении, но не о том, что всё починилось.
Gatus поддерживает также Discord, PagerDuty, Opsgenie, Mattermost, Matrix, Ntfy, Pushover, generic webhook и почту — конфигурация везде однотипная: блок с учётными данными в alerting, ссылка на тип в alerts эндпоинта.
Метрики Prometheus и интеграция с Grafana
Если у вас уже развёрнут стек мониторинга, Gatus отдаёт метрики в формате Prometheus на /metrics — достаточно включить флаг в конфиге:
metrics: true
И добавить джоб в prometheus.yml (или соответствующий scrape-конфиг вашего Prometheus, если он в отдельном контейнере в той же docker-сети):
scrape_configs:
- job_name: "gatus"
static_configs:
- targets: ["gatus:8080"]
Основные метрики — gatus_results_total (счётчик проверок с лейблами key и success) и gatus_results_duration_seconds (гистограмма времени ответа). Этого достаточно, чтобы построить в Grafana панель аптайма по сервисам и алерты через Alertmanager — если у вас уже стоит связка, подробности в статье про Grafana и Prometheus на сервере. Держать при этом отдельно и алерты Gatus, и алерты Alertmanager по тем же метрикам избыточно — выберите один источник правды, иначе на одно падение будете получать по два разных сообщения.
Безопасность: доступ к статус-странице и обратный прокси
Три момента, которые стоит закрыть до того, как статус-страница уйдёт наружу:
- Не публикуйте порт 8080 напрямую в интернет без прокси. У Gatus нет встроенной аутентификации, а публичная статус-страница — это, по сути, карта того, какие у вас есть внутренние сервисы и когда они падают. Для внешнего доступа поставьте перед ним Nginx или Traefik с TLS и, если страница не должна быть полностью открытой, с basic-auth.
- Не давайте Gatus доступ туда, куда ему не нужно. Если вы проверяете внутренние сервисы по имени контейнера (
http://api:3000/health), подключайте Gatus только к тем docker-сетям, где реально лежат проверяемые контейнеры, а не ко всем сетям на хосте.
- Токены алертов — это секреты. Токен Telegram-бота или webhook Slack в открытом
config.yamlв публичном git-репозитории — частая утечка. Вынесите чувствительные значения через переменные окружения (${GATUS_TELEGRAM_TOKEN}с подстановкой из.env-файла, который не коммитится) либо черезdocker secrets, если Gatus у вас развёрнут в Swarm-стеке — про это в статье про Docker secrets и управление паролями.
Пример с переменными окружения в compose-файле:
services:
gatus:
image: twinproduction/gatus:latest
env_file:
- .env
environment:
- GATUS_CONFIG_PATH=/config
А в config.yaml — token: "${GATUS_TELEGRAM_TOKEN}", Gatus сам подставит значение из окружения при старте.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Gatus теряет историю проверок при перезапуске контейнера?
Нет, если том /data смонтирован и в конфиге указан storage.type: sqlite (или postgres) с путём внутри этого тома — история переживает docker compose down и up. Если storage не настроен, Gatus держит последние результаты только в памяти, и после рестарта график начинается заново.
Можно ли проверять сервисы без публичного домена, только по внутреннему имени контейнера?
Да, это основной сценарий для мониторинга docker-инфраструктуры — укажите url: "http://service-name:port/health", где service-name — имя сервиса в той же docker-сети, и Gatus достучится до него по внутреннему DNS Docker.
Чем Gatus отличается от healthcheck в самом docker-compose.yml?
Docker healthcheck — это внутренняя проверка живости контейнера для самого Docker (перезапуск, статус healthy/unhealthy), она не даёт истории, статус-страницы и алертов наружу. Gatus — внешний наблюдатель поверх всего этого, который видит доступность с точки зрения клиента и умеет уведомлять людей. Подробнее о самом механизме — в статье про настройку docker healthcheck.
Что делать, если алерты в Telegram не приходят?
Проверьте логи контейнера (docker logs gatus) — там видны ошибки отправки; частые причины — неверный chat id (для групп он отрицательный и начинается с -100), бот не добавлен в группу или не имеет прав писать сообщения.
Нужен ли Gatus отдельный сервер или хватит того же, где крутятся сайты?
Хватит того же — Gatus потребляет минимум ресурсов (десятки мегабайт памяти в простое), поэтому его обычно ставят рядом с остальными сервисами на том же VPS, а не выделяют под него отдельную машину.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →