Когда веб-сайт или приложение падает посреди ночи, узнать об этом первым из чужих гневных сообщений в техподдержку - худший сценарий для любого администратора. Гораздо комфортнее иметь собственную систему мониторинга, которая просыпается раньше пользователей и сразу шлёт уведомление в нужный канал. На рынке таких решений хватает - Pingdom, UptimeRobot, StatusCake и десяток других облачных сервисов готовы взять на себя эту работу за ежемесячную плату. Но есть и альтернатива из мира открытого ПО - Statping, или точнее его актуальный форк Statping-ng, потому что оригинальный проект давно заброшен оригинальным разработчиком и развивается сообществом.

Statping умеет отслеживать доступность HTTP-эндпоинтов, открытость TCP-портов, отвечает ли ICMP, корректно ли работают конкретные методы API. Результаты проверок ложатся в базу данных и превращаются в красивые публичные страницы статуса вроде тех, что показывают AWS, GitHub или Stripe в моменты массовых проблем. Поддерживаются уведомления через email, Slack, Telegram и десяток других каналов. Хранилище данных гибкое - можно использовать SQLite для домашних экспериментов или подключить PostgreSQL и MySQL для серьёзных инсталляций.

В материале разбирается развёртывание Statping на сервере с Ubuntu 22.04 по современной схеме - через Docker Compose с PostgreSQL в качестве базы, Nginx в качестве реверс-прокси и SSL-сертификатом от Let's Encrypt. К концу прочтения у читателя получится рабочая страница статуса с админкой для добавления отслеживаемых сервисов и публичным дашбордом для пользователей.

Подготовка окружения и настройка брандмауэра UFW для приёма входящего веб-трафика

Любая установка серьёзного сервиса начинается с приведения системы в актуальное состояние. На свежем сервере полезно сразу же подтянуть все доступные обновления безопасности.

$ sudo apt update && sudo apt upgrade

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

После обновлений нужно убедиться, что брандмауэр настроен правильно и пропускает то, что нужно. UFW по умолчанию идёт с консервативными настройками - открыт только SSH, всё остальное закрыто.

$ sudo ufw status

На свежем сервере вывод обычно выглядит так.

Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)

Веб-сервис будет жить на портах 80 и 443, поэтому их нужно открыть для входящих соединений.

$ sudo ufw allow http
$ sudo ufw allow https

UFW автоматически распознаёт символьные имена сервисов и преобразует их в номера портов через файл /etc/services. Под капотом эти команды разрешают TCP-соединения на 80-й и 443-й порты соответственно. Альтернативный синтаксис с явным указанием номеров портов вроде sudo ufw allow 80/tcp дал бы тот же результат.

Повторная проверка статуса показывает обновлённую картину.

$ sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
80/tcp                     ALLOW       Anywhere
443                        ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
80/tcp (v6)                ALLOW       Anywhere (v6)
443 (v6)                   ALLOW       Anywhere (v6)

Брандмауэр готов пропускать веб-трафик. Все остальные порты остаются закрытыми, что правильно с точки зрения безопасности - наружу торчит только то, что должно торчать наружу.

Установка движка контейнеризации Docker и плагина Compose из официального репозитория проекта

Statping в современной поставке распространяется как Docker-образ, поэтому без контейнеризации никуда. Версия Docker из стандартных репозиториев Ubuntu обычно отстаёт от актуальной на несколько релизов, и для свежих фич лучше подключить официальный репозиторий проекта.

Сначала добавляется GPG-ключ для проверки подписи пакетов.

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker.gpg

Команда сразу выполняет несколько действий через пайп. Curl скачивает GPG-ключ Docker в текстовом ASCII-armored формате, после чего gpg --dearmor преобразует его в бинарный формат и сохраняет в системный каталог keyrings. Флаги curl стоят пояснения - буква f заставляет утилиту молча падать при HTTP-ошибках, s включает silent-режим, S при этом сохраняет вывод реальных ошибок, L разрешает следовать редиректам.

Дальше подключается сам репозиторий с привязкой к скачанному ключу.

$ echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Внутри строки происходит интересное - подстановка команд через $(...). Команда dpkg --print-architecture возвращает архитектуру системы (amd64 для 64-битных x86 серверов, arm64 для ARM-процессоров), а lsb_release -cs выдаёт кодовое имя релиза Ubuntu (jammy для 22.04). В итоге собирается полная строка репозитория, конкретная для текущего сервера. Параметр signed-by привязывает репозиторий к ранее установленному GPG-ключу - это современный подход к безопасной верификации пакетов.

После добавления репозитория обновляются индексы и устанавливается сам Docker.

$ sudo apt update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin

Список устанавливаемых пакетов осмысленный. docker-ce - сам движок контейнеризации, docker-ce-cli - клиент командной строки, containerd.io - низкоуровневая среда выполнения контейнеров, docker-compose-plugin - современный плагин Compose v2. Туториал использует именно плагинную версию вместо старого отдельного бинарника docker-compose, что приводит к небольшой смене синтаксиса. Команда теперь пишется через пробел - docker compose вместо docker-compose с дефисом. Поведение и набор функций остаются практически идентичными.

Запуск Docker-команд требует root-привилегий по умолчанию, потому что движок управляет процессами и сетями системы. Постоянно писать sudo перед каждой командой утомительно. Решение - добавить пользователя в группу docker.

$ sudo usermod -aG docker ${USER}

Переменная ${USER} раскрывается в имя текущего залогиненного пользователя. Если команда выполняется от root, нужно явно подставить нужное имя вместо переменной. Флаг -a (append) важен - без него usermod заменит все дополнительные группы пользователя на указанную, а с ним добавит новую к существующим.

Изменения членства в группах вступают в силу только при новой сессии. Можно перелогиниться по SSH или использовать команду su для перезагрузки контекста.

$ su - ${USER}

Дефис после su означает создание полноценной login-сессии с полной перезагрузкой переменных окружения. Без него получится промежуточное состояние с частично обновлённым контекстом, что иногда даёт странные эффекты.

Установка веб-сервера Nginx и получение SSL-сертификата от Let's Encrypt через Certbot

Перед Statping будет стоять Nginx как реверс-прокси, отвечающий за SSL-терминирование и проксирование запросов на контейнер. Версия из дистрибутивных репозиториев Ubuntu тоже устарела, поэтому правильно подключить официальный репозиторий разработчиков Nginx.

$ curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null

Логика та же, что и с Docker - скачивается публичный ключ репозитория, преобразуется в бинарный формат и сохраняется в системный каталог. Перенаправление в /dev/null в конце нужно, чтобы tee не печатал содержимое в консоль (без этого терминал бы засыпало бинарными данными).

Подключение самого репозитория.

$ echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg arch=amd64] \
http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list

Обратные кавычки вокруг lsb_release - это устаревший синтаксис подстановки команд, эквивалентный современному $(...). Оба варианта работают одинаково, но в новых скриптах принято писать через доллар-скобки для лучшей читаемости и поддержки вложенных подстановок.

Дальше стандартное обновление и установка.

$ sudo apt update
$ sudo apt install nginx

Проверка успешной установки.

$ nginx -v
nginx version: nginx/1.22.0

Версия должна быть свежее, чем в дистрибутивных репозиториях. На момент написания туториала это была 1.22, но цифра меняется по мере выхода новых релизов.

Следующий блок работы - SSL-сертификат. Для его получения используется Certbot, официальный клиент Let's Encrypt. Самый удобный способ установить свежую версию - через snap, потому что в нём всегда лежит актуальный релиз без задержек на пересборку дистрибутивных пакетов.

$ sudo snap install core

Эта команда устанавливает или обновляет базовый snap-пакет core, на котором работают все остальные snap-приложения.

Сам Certbot ставится в classic-режиме, который даёт пакету полный доступ к системе без обычной snap-изоляции.

$ sudo snap install --classic certbot

Чтобы команда certbot вызывалась без полного пути из любого места, делается символическая ссылка в /usr/bin.

$ sudo ln -s /snap/bin/certbot /usr/bin/certbot

Получение самого сертификата выполняется одной развёрнутой командой со множеством параметров.

$ sudo certbot certonly --standalone --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в браузере должен быть включен Javascript. -d status.example.com

Каждый флаг тут осмыслен. Режим certonly означает только получение сертификата без автоматической настройки веб-сервера - конфиг Nginx будет писаться вручную позже. Параметр --standalone запускает временный мини-сервер Certbot для прохождения проверки владения доменом - именно поэтому Nginx должен быть остановлен в момент работы команды (если бы он уже работал, два процесса не смогли бы поделить 80-й порт). Флаг --agree-tos автоматически соглашается с пользовательским соглашением Let's Encrypt без интерактивного запроса. Параметр --no-eff-email отказывается от рассылки от Electronic Frontier Foundation. Опция --staple-ocsp включает поддержку OCSP-степлинга. Параметр --preferred-challenges http выбирает HTTP-валидацию вместо DNS - для этого нужен открытый 80-й порт и корректная DNS-запись на этот сервер. После -m идёт контактный email, после -d - доменное имя.

Сертификат сохраняется в каталог /etc/letsencrypt/live/status.example.com/ со всеми нужными файлами.

Для усиления криптографии генерируется группа Диффи-Хеллмана с большим ключом.

$ sudo openssl dhparam -dsaparam -out /etc/ssl/certs/dhparam.pem 4096

Параметр -dsaparam ускоряет генерацию в десятки раз без существенной потери стойкости. Без него ожидание могло бы растянуться на час и больше на слабом сервере.

Сертификаты Let's Encrypt живут только 90 дней, поэтому критически важно настроить автоматическое продление с правильной обработкой Nginx.

$ sudo nano /etc/letsencrypt/renewal/status.example.com.conf

В конец файла добавляются хуки для остановки и запуска Nginx.

pre_hook = systemctl stop nginx
post_hook = systemctl start nginx

Pre-hook выполняется перед обновлением сертификата, post-hook - после. Standalone-метод требует свободного 80-го порта, поэтому Nginx останавливается на пару минут на время процедуры. Без этих хуков продление сломалось бы при первом же автоматическом запуске.

Проверка работоспособности схемы продления через симуляцию.

$ sudo certbot renew --dry-run

Если ошибок нет, всё в порядке - сертификат будет автоматически продляться через системный таймер каждые два месяца без вмешательства человека.

Создание docker-compose файла с описанием связки приложения Statping и базы данных PostgreSQL

Теперь главное - описание самого приложения через docker-compose.yml. Сначала создаётся отдельный каталог под все файлы Statping.

$ mkdir ~/statping
$ cd ~/statping

Внутри открывается на редактирование файл с описанием стека.

$ nano docker-compose.yml

Содержимое получается развёрнутым, но логичным.

services:
  statping:
    container_name: statping
    image: adamboutcher/statping-ng
    restart: always
    ports:
      - 8080:8080
    volumes:
      - ./statping_data:/app
    links:
      - postgres
    depends_on:
      - postgres
    environment:
      DB_CONN: postgres
      DB_HOST: postgres
      DB_PORT: 5432
      DB_DATABASE: statping
      DB_USER: root
      DB_PASS: password123
      NAME: 'Howtoforge Statping page'
      DESCRIPTION: 'Statping Demo page'
      USE_ASSETS: 'true'
      SAMPLE_DATA: 'false'
      ALLOW_REPORTS: 'false'
      ADMIN_USER: navjot
      ADMIN_PASSWORD: yourpassword

  postgres:
    container_name: postgres
    image: postgres:14-alpine
    ports:
      - 5432:5432
    volumes:
      - ./pg_data:/var/lib/postgresql/data/pg_data
    environment:
      POSTGRES_PASSWORD: password123
      POSTGRES_DB: statping
      POSTGRES_USER: root
      POSTGRES_PORT: 5432
      PGDATA: /var/lib/postgresql/data/pg_data

Файл описывает два сервиса - сам Statping и базу данных PostgreSQL. Каждый блок заслуживает разбора.

Контейнер statping использует образ adamboutcher/statping-ng - это форк оригинального заброшенного проекта, который сейчас активно поддерживается. Параметр restart: always означает перезапуск контейнера при любом завершении, включая перезагрузку Docker-демона и всей системы. Проброс портов 8080:8080 делает приложение доступным на восьмитысячном порту хоста. Том ./statping_data:/app монтирует локальный каталог в контейнер для хранения файлов приложения - конфигов, настроек, загруженных активов. Без этой привязки данные терялись бы при пересоздании контейнера.

Директивы links и depends_on управляют взаимосвязями между контейнерами. Links устанавливает сетевую связь, depends_on задаёт порядок запуска - PostgreSQL поднимается раньше Statping, потому что приложению нужна работающая база при старте.

Блок environment содержит переменные окружения для настройки приложения. Часть из них стоит разобрать подробно.

DB_CONN, DB_HOST, DB_PORT, DB_DATABASE, DB_USER, DB_PASS - параметры подключения к базе. Они должны точно совпадать с настройками PostgreSQL-контейнера, иначе соединение не установится. Имя хоста postgres работает благодаря Docker-сети, которая автоматически создаётся для compose-стека и резолвит имена контейнеров в их IP-адреса.

NAME и DESCRIPTION задают название и описание страницы статуса, которые будут видны пользователям.

USE_ASSETS со значением true разрешает приложению использовать ассеты из локальной папки - это нужно для кастомизации внешнего вида (загрузка собственных логотипов, иконок, стилей).

SAMPLE_DATA со значением false отключает генерацию демо-данных при первом запуске. Если оставить true, Statping создаст несколько фиктивных сервисов для демонстрации возможностей. Для боевой инсталляции это лишнее.

ALLOW_REPORTS со значением false отключает анонимную отправку отчётов об ошибках разработчикам. Если важна приватность инсталляции, эту опцию точно нужно отключить.

ADMIN_USER и ADMIN_PASSWORD задают начальные учётные данные администратора. Эти значения хранятся в открытом виде в compose-файле, поэтому он сам должен лежать в защищённом каталоге с правильными правами.

Блок postgres описывает контейнер базы данных. Используется официальный образ postgres:14-alpine - четырнадцатая версия PostgreSQL на минималистичной Alpine Linux. Alpine-образы заметно меньше по размеру обычных, что экономит место на диске и ускоряет скачивание. Том ./pg_data монтирует локальный каталог для хранения данных базы - без него вся информация о сервисах, проверках, истории доступности терялась бы при пересоздании контейнера.

Переменные POSTGRES_* настраивают саму базу при первом запуске - устанавливают пароль пользователя root, создают базу statping, задают порт. PGDATA указывает кастомный путь для размещения файлов данных внутри контейнера, который совпадает с точкой монтирования тома.

После сохранения файла compose-стек готов к запуску, но сначала нужно настроить Nginx.

Конфигурация Nginx как обратного прокси с современными настройками TLS и поддержкой HTTP/2

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

$ sudo nano /etc/nginx/nginx.conf

Перед строкой include /etc/nginx/conf.d/*.conf; добавляется одна директива.

server_names_hash_bucket_size  64;

Дальше создаётся отдельный конфиг под нашу страницу статуса.

$ sudo nano /etc/nginx/conf.d/statusping.conf

Содержимое получается насыщенным современными настройками безопасности.

upstream backend {
   server 127.0.0.1:8080;
   keepalive 32;
}

server {
  listen 80 default_server;
  server_name status.example.com;
  return 301 https://$server_name$request_uri;
}

server {
   listen 443 ssl http2;
   server_name status.example.com;

   http2_push_preload on; # Enable HTTP/2 Server Push

   ssl_certificate /etc/letsencrypt/live/status.example.com/fullchain.pem;
   ssl_certificate_key /etc/letsencrypt/live/status.example.com/privkey.pem;
   ssl_trusted_certificate /etc/letsencrypt/live/status.example.com/chain.pem;
   ssl_session_timeout 1d;

   # Enable TLS versions (TLSv1.3 is required upcoming HTTP/3 QUIC).
   ssl_protocols TLSv1.2 TLSv1.3;

   # Enable TLSv1.3's 0-RTT. Use $ssl_early_data when reverse proxying to
   # prevent replay attacks.
   #
   # @see: https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_early_data
   ssl_early_data on;

   ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384';
   ssl_prefer_server_ciphers on;
   ssl_session_cache shared:SSL:50m;
   # OCSP Stapling --- fetch OCSP records from URL in ssl_certificate and cache them
   ssl_stapling on;
   ssl_stapling_verify on;
   ssl_dhparam /etc/ssl/certs/dhparam.pem;

   add_header X-Early-Data $tls1_3_early_data;

   access_log /var/log/nginx/statusping.access.log main;
   error_log  /var/log/nginx/statusping.error.log;

   location / {
       client_max_body_size 50M;
       proxy_set_header Connection "";
       proxy_set_header Host $http_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;
       proxy_set_header X-Frame-Options SAMEORIGIN;
       proxy_set_header X-Client-Verify  SUCCESS;
       proxy_set_header X-Client-DN      $ssl_client_s_dn;
       proxy_set_header X-SSL-Subject    $ssl_client_s_dn;
       proxy_set_header X-SSL-Issuer     $ssl_client_i_dn;
       proxy_buffers 256 16k;
       proxy_buffer_size 16k;
       proxy_read_timeout 1800s;
       proxy_connect_timeout 1800s;
       proxy_http_version 1.1;
       proxy_pass http://backend;
   }
}

# This block is useful for debugging TLS v1.3. Please feel free to remove this
# and use the `$ssl_early_data` variable exposed by NGINX directly should you
# wish to do so.
map $ssl_early_data $tls1_3_early_data {
  "~." $ssl_early_data;
  default "";
}

Конфиг плотный, с множеством полезных директив. Блок upstream объявляет именованный пул с одним бэкендом на локальном порту 8080 - именно туда смотрит контейнер Statping. Параметр keepalive 32 держит до 32 готовых TCP-соединений с бэкендом для повторного использования, экономя время на установлении новых сессий.

Первый server-блок ловит весь HTTP-трафик и редиректит его на HTTPS-версию. Это стандартный паттерн принудительного шифрования - открытый протокол должен быть только дверью к закрытому.

Второй server-блок и есть основное действие. Он слушает 443-й порт с включённым SSL и HTTP/2. Поддерживаются только современные протоколы TLS 1.2 и 1.3, всё устаревшее отключено. Параметр ssl_early_data включает 0-RTT - механизм TLS 1.3, позволяющий клиенту отправить первый запрос вместе с самым первым пакетом подключения, без ожидания завершения handshake. Прирост скорости заметен особенно на мобильных сетях с большим RTT.

Список шифров жёстко зафиксирован и содержит только проверенные алгоритмы с эфемерными ключами Диффи-Хеллмана на эллиптических кривых (ECDHE). Это даёт forward secrecy - защиту от расшифровки старого трафика даже при компрометации приватного ключа в будущем.

OCSP-степлинг через ssl_stapling позволяет Nginx самому получать у Let's Encrypt подтверждение валидности сертификата и прикреплять его к ответам, избавляя клиентов от лишних обращений к серверам Let's Encrypt при каждом подключении.

Блок location обрабатывает все запросы и проксирует их на бэкенд-контейнер. Заголовки X-Real-IP, X-Forwarded-For и X-Forwarded-Proto передают приложению информацию об оригинальном клиенте - реальный IP, протокол, имя хоста. Без них Statping видел бы все запросы как идущие с 127.0.0.1, что сломало бы любую логику ограничения доступа по IP, аналитику и логирование.

Заголовки proxy_set_header X-SSL-* передают информацию о клиентском сертификате, если он используется при подключении. Для базовой инсталляции без mutual TLS они не нужны, но и не мешают.

Параметры proxy_read_timeout и proxy_connect_timeout выставлены в 1800 секунд (полчаса) - это щедрые таймауты для случаев, когда Statping выполняет долгую операцию вроде регенерации статистики за большой период.

Перед перезапуском Nginx обязательна проверка синтаксиса.

$ sudo nginx -t
$ sudo systemctl restart nginx

После рестарта прокси готов принимать соединения.

Запуск контейнерного стека и первоначальная настройка приложения через веб-интерфейс

Когда Nginx настроен, можно поднимать сами контейнеры. Переход в каталог с compose-файлом и запуск.

$ cd ~/statping
$ docker compose up -d

Флаг -d (detached) запускает контейнеры в фоновом режиме, чтобы терминал не был привязан к их выводу. Docker скачает образы Statping-ng и PostgreSQL (если их ещё нет в локальном реестре), создаст сеть для общения контейнеров между собой, поднимет тома для постоянного хранения данных и запустит сервисы в правильном порядке.

После завершения запуска можно проверить состояние стека.

$ docker compose ps
NAME                COMMAND                  SERVICE             STATUS              PORTS
postgres            "docker-entrypoint.s…"   postgres            running             0.0.0.0:5432->5432/tcp
statping            "/bin/sh -c 'statpin…"   statping            running (healthy)   0.0.0.0:8080->8080/tcp

Оба контейнера в статусе running, причём Statping уже healthy - значит встроенные проверки здоровья прошли успешно. Если бы что-то пошло не так, статус был бы unhealthy или контейнер вообще не стартовал. Для подробной диагностики помогают команды docker ps и docker logs <container_name> - они показывают полные логи каждого контейнера со всеми сообщениями о запуске.

Открыв в браузере адрес https://status.example.com, посетитель видит чистую страницу статуса. Поскольку SAMPLE_DATA выставлен в false, никаких демо-сервисов нет - страница показывает базовый каркас, готовый к наполнению.

Внизу страницы есть ссылка Dashboard, которая ведёт на форму входа в админку. Логин по умолчанию admin/admin (несмотря на ADMIN_USER и ADMIN_PASSWORD в compose-файле, при первом запуске Statping показывает свои дефолтные значения). Нужно явно ввести оба значения, даже если поле логина выглядит предзаполненным.

После авторизации открывается полноценный дашборд администратора. Главное действие тут - нажать кнопку Create и добавить первый отслеживаемый сервис. Нужно указать имя сервиса, тип проверки (HTTP, TCP, ICMP), URL или адрес для проверки, интервал между запросами, ожидаемый код ответа. Statping начинает выполнять проверки сразу после сохранения и быстро накапливает статистику.

Через настройки можно поменять название страницы, описание, подключить уведомления через email, Slack, Telegram и десяток других каналов. Каждое уведомление настраивается отдельно с возможностью указать конкретные условия отправки - падение сервиса, восстановление, превышение времени ответа выше порога.

Обновление установки до актуальной версии без потери накопленных данных и итоговые соображения о ценности развёрнутой системы

Со временем выходят новые версии Statping с исправлениями ошибок и новыми фичами. Обновление в Docker-инсталляции делается элегантно и быстро.

$ cd ~/statping

Сначала останавливаются и удаляются текущие контейнеры. Данные при этом не теряются, потому что они лежат на томах, привязанных к локальному файловому пути.

$ docker compose down --remove-orphans

Флаг --remove-orphans удаляет контейнеры, которые упоминались в старых версиях compose-файла, но больше не определены. Полезно при перестройке стека.

Скачивание свежих версий образов.

$ docker compose pull

Запуск стека заново уже на новых образах.

$ docker compose up -d

Statping подхватит данные из существующих томов и продолжит работу с того же места, где остановился. Вся история проверок, настроенные сервисы, учётные записи администраторов - всё сохраняется. В этом и есть прелесть Docker-инсталляций - обновление приложения занимает три команды и пару минут, без необходимости разбираться в миграциях баз данных или конфликтах конфигов.

Развёрнутый Statping - это полноценная система мониторинга, которой можно пользоваться годами. Для команды разработки с десятком - двумя сервисов получившейся производительности хватит с большим запасом. Если потребуется отслеживать сотни эндпоинтов, придётся думать об оптимизации - либо тюнинг PostgreSQL под нагрузку, либо переход на более распределённое решение вроде Prometheus с Alertmanager. Но для большинства реальных команд Statping остаётся золотой серединой между голым curl в crontab и сложными корпоративными платформами.

Публичная страница статуса - это ещё и инструмент коммуникации с пользователями. Когда что-то падает, ссылка на красивый дашборд в письме клиентам выглядит куда профессиональнее сухого технического оправдания. Видно, какие именно сервисы затронуты, сколько времени длится инцидент, какие компоненты работают штатно. Прозрачность снимает большую часть вопросов и снижает нагрузку на техподдержку. Освоение Statping и подобных систем - это не просто настройка ещё одного сервиса, а шаг к более зрелой эксплуатационной культуре, где всё измеримо, видимо и подконтрольно.