Sentry (self-hosted) в Docker Compose: готовый файл
Ищете «просто docker-compose.yml для Sentry, чтобы скопировать и запустить» — и упираетесь в то, что готового куска YAML на 15 строк для этой задачи не существует в природе. Self-hosted Sentry — это полтора десятка сервисов с внутренними зависимостями, и честный ответ звучит иначе: файл вы получаете официальным генератором, а дальше учитесь с ним работать — понимать структуру, безопасно донастраивать под свой сервер и не терять правки при обновлениях. Ниже — разбор того, что реально лежит в этом файле, и рабочий способ подогнать его под себя без разрушения обновляемости.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Почему нет универсального docker-compose.yml на 20 строк
У большинства сервисов из серии «докер-компоуз, готовый файл» действительно достаточно одного контейнера и пары переменных окружения. Sentry устроен иначе: чтобы принять событие с ошибкой, обработать его и показать в интерфейсе, одновременно работают:
- Postgres — хранит проекты, пользователей, настройки, релизы, алерты;
- Redis — очереди задач и кеш;
- Kafka + Zookeeper — шина событий между воркерами обработки;
- ClickHouse — колоночная база, куда фактически ложатся события и трассировки;
- Snuba (несколько контейнеров:
api,consumer,outcomes-consumer,replacer,cleanupи другие) — прослойка между Kafka/ClickHouse и остальным Sentry; - Relay — приёмный шлюз, который первым получает событие от SDK;
- Symbolicator — разбирает нативные стектрейсы (крэши мобильных и десктопных приложений);
- web, worker, cron — сам Sentry: интерфейс, фоновые задачи, планировщик;
- nginx — точка входа внутри compose-сети.
Написать всё это вручную с нуля — не только долго, но и рискованно: версии сервисов в разных релизах Sentry жёстко привязаны друг к другу (конкретная Kafka под конкретную Snuba под конкретный ClickHouse), и малейшее расхождение ломает обработку событий на ровном месте с непонятной ошибкой в логах воркера. Поэтому практика, которая реально работает — не писать файл заново, а взять генератор от разработчиков и относиться к результату как к вендорному конфигу, который вы контролируемо расширяете сверху. Это ровно та же логика, что и с Docker Compose для продакшена в целом — базовый файл плюс слой собственных правок.
Как получить актуальный файл
Полный процесс установки с нуля — в отдельной статье про установку Sentry self-hosted на VPS. Здесь — только то, что касается самого файла:
cd /opt
git clone https://github.com/getsentry/self-hosted.git sentry
cd sentry
git checkout 24.9.1 # берите конкретный тег, не master
./install.sh
После install.sh в каталоге /opt/sentry появляется рабочий docker-compose.yml — это не шаблон для ручного заполнения, а полностью собранный файл с проставленными версиями образов, сетями и volume'ами, синхронизированными с конкретным релизом. Именно его вы дальше и держите под git внутри своей инфраструктуры — как обычный конфиг сервера, а не как временный артефакт установки.
git -C /opt/sentry diff HEAD~1 -- docker-compose.yml # что изменилось после апдейта
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверСтруктура сгенерированного файла: что там на самом деле
Фрагмент реальной структуры (сокращённо, без полных версий образов — они меняются от релиза к релизу):
services:
redis:
image: redis:...
restart: unless-stopped
volumes:
- sentry-redis:/data
postgres:
image: getsentry/postgres-exporter... # либо официальный postgres-образ
restart: unless-stopped
environment:
- POSTGRES_HOST_AUTH_METHOD=trust
volumes:
- sentry-postgres:/var/lib/postgresql/data
kafka:
image: confluentinc/cp-kafka:...
restart: unless-stopped
depends_on:
- zookeeper
clickhouse:
image: clickhouse/clickhouse-server:...
restart: unless-stopped
ulimits:
nofile:
soft: 262144
hard: 262144
volumes:
- sentry-clickhouse:/var/lib/clickhouse
web:
image: getsentry/sentry:...
restart: unless-stopped
depends_on:
- postgres
- redis
- kafka
env_file: .env
volumes:
- sentry-data:/data
nginx:
image: nginx:...
restart: unless-stopped
ports:
- "9000:80"
depends_on:
- web
Смысл в том, что этот файл не рассчитан на построчное редактирование руками — при следующем ./install.sh (например, при обновлении версии) он перезапишется целиком, и любая ваша правка внутри него исчезнет. Официальная и единственная безопасная точка кастомизации — файл .env рядом (переменные SENTRY_*, порты, retention) и отдельный docker-compose.override.yml, который Docker Compose подхватывает автоматически и накладывает поверх основного файла, не трогая оригинал.
Свои правки через docker-compose.override.yml
Override-файл — стандартный механизм Compose: docker compose up сам подхватывает docker-compose.override.yml из той же папки и мёржит его с основным файлом по именам сервисов. Это ровно тот слой, где живут все ваши изменения — без риска потерять их при апдейте Sentry. Общий подход к разным окружениям через такие слои разобран в статье про Docker Compose profiles.
Пример — ограничение памяти под ClickHouse и Kafka (часто первое, что требуется на VPS с 8 ГБ RAM), плюс перенос порта веб-интерфейса на нестандартный:
# /opt/sentry/docker-compose.override.yml
services:
clickhouse:
mem_limit: 3g
environment:
- CLICKHOUSE_MAX_MEMORY_USAGE=2800000000
kafka:
mem_limit: 1.5g
environment:
- KAFKA_HEAP_OPTS=-Xmx768m -Xms768m
nginx:
ports:
- "127.0.0.1:9000:80" # закрываем прямой доступ снаружи
После правки docker-compose.override.yml пересобирать ничего не нужно — просто:
cd /opt/sentry
docker compose up -d
docker compose config # показывает итоговый файл после мёржа — удобно для проверки
docker compose config — команда, которую стоит держать в привычке при работе с override-слоями: она печатает результирующий YAML после объединения всех файлов, и по нему сразу видно, применилась ли ваша правка так, как вы задумывали, ещё до запуска контейнеров.
Свой reverse proxy вместо встроенного nginx
Стандартный docker-compose.yml от Sentry сам поднимает nginx-контейнер и слушает порт наружу. Если на сервере уже есть общий реверс-прокси для нескольких сервисов — логичнее не держать второй nginx только ради Sentry, а завести его в общую docker-сеть и убрать проброс портов у встроенного nginx через тот же override:
# docker-compose.override.yml
networks:
proxy-net:
external: true
services:
nginx:
ports: [] # убираем прямой проброс наружу
networks:
- default
- proxy-net
labels:
- "traefik.enable=true"
- "traefik.http.routers.sentry.rule=Host(`sentry.example.com`)"
- "traefik.http.routers.sentry.entrypoints=websecure"
- "traefik.http.routers.sentry.tls.certresolver=letsencrypt"
- "traefik.http.services.sentry.loadbalancer.server.port=80"
Это тот же принцип, что описан в статье Traefik как reverse proxy для докера — контейнер подключается к внешней сети прокси по имени, и Traefik сам находит его по labels, без ручной прописи портов и без дублирования SSL-терминации в двух местах.
Ресурсы и типичные ошибки первого запуска
Ориентир по серверу для честного запуска всего стека — минимум 4 vCPU и 8 ГБ RAM, комфортно — от 16 ГБ; это не измеренный бенчмарк, а порог, ниже которого Kafka и ClickHouse начинают конкурировать за память и валиться в перезапуск по кругу. Диск — от 60 ГБ, с ростом по мере накопления событий в ClickHouse.
| Что настроено не так | Симптом | Где чинить |
|---|---|---|
vm.max_map_count не увеличен | ClickHouse/Kafka не стартуют, max virtual memory areas ... too low | sysctl -w vm.max_map_count=262144 на хосте |
Правки внесены прямо в docker-compose.yml | Правки пропадают после ./install.sh при обновлении | Перенести в docker-compose.override.yml |
Нет mem_limit у ClickHouse/Kafka | OOM-килы контейнеров под нагрузкой на слабом VPS | Задать лимиты в override (пример выше) |
| Два nginx/reverse proxy слушают один порт | bind: address already in use при старте | Убрать проброс портов у встроенного nginx, завести в сеть общего прокси |
Забыт .env после git checkout на новый тег | web не стартует, ругается на отсутствующие переменные | ./install.sh заново применяет и досоздаёт .env, не трогая существующие значения |
Диагностика при проблемах со стартом — стандартная связка команд:
docker compose ps
docker compose logs --tail 100 clickhouse
docker compose logs --tail 100 snuba-consumer
docker compose config # проверить итоговый файл после override
Если контейнеры регулярно упираются в лимиты и непонятно, что именно ест ресурс сервера в целом, а не только в рамках стека Sentry — общий подход к лимитам разобран в статье про ресурсы и лимиты CPU и памяти в Docker.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Можно ли просто скопировать чей-то docker-compose.yml для Sentry из интернета и запустить?
Не стоит. Версии сервисов в файле жёстко привязаны к конкретному релизу Sentry, и файл из чужого репозитория почти наверняка окажется рассинхронизирован с версией, которую вы разворачиваете — получите падающие миграции ClickHouse или воркеры, которые не могут разобрать формат сообщений в Kafka. Берите файл только через официальный install.sh под нужный тег.
Что делать, если я уже правил docker-compose.yml напрямую, а теперь нужно обновление?
Сохраните ваши изменения (git diff покажет их, если файл под git), перенесите их в docker-compose.override.yml, затем откатите основной файл к чистому состоянию перед ./install.sh — иначе установщик может отказаться накатывать обновление поверх изменённого файла.
Нужен ли docker-compose.override.yml, если я ничего не меняю в конфигурации?
Нет, без override файл работает как есть — он нужен только тогда, когда требуется что-то поверх стандартного поведения: свои лимиты памяти, порты, сеть для внешнего прокси.
Почему нельзя просто урезать файл, убрав Kafka и ClickHouse ради экономии ресурсов?
В версиях Sentry после перехода на архитектуру Snuba эти сервисы обязательны для обработки событий — без них не поднимется даже веб-интерфейс. Урезанные конфигурации без них существовали только в очень старых релизах (9.x), которые давно не получают обновлений безопасности.
Как проверить, что override действительно применился, а не проигнорирован?
Команда docker compose config печатает итоговый YAML после мёржа всех файлов — ищите в выводе именно те значения, которые задавали в override, а не значения по умолчанию из основного файла.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →