Metabase на сервере: частые ошибки и решения
Metabase подкупает тем, что дашборды строит любой аналитик без единой строчки SQL, а разворачивается — одним контейнером за пять минут. Именно эта простота и подводит: люди запускают его на минимальной VPS, забывают про память для JVM, теряют настройки при обновлении образа — и потом часами гуглят непонятные ошибки в логах. Ниже — конкретные проблемы, с которыми сталкиваются на реальных серверах, и рабочие решения без домыслов.
Содержание
- Metabase не стартует: контейнер падает или зависает на «Starting Metabase»
- Нехватка памяти: почему Metabase требует больше RAM, чем кажется
- Потеря настроек и дашбордов после перезапуска или обновления образа
- Подключение к источникам данных: тайм-ауты и ошибки доступа
- Медленные дашборды и запросы, которые «вешают» интерфейс
- Metabase недоступен снаружи или падает SSL
- Обновление Metabase без риска всё сломать
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Metabase не стартует: контейнер падает или зависает на «Starting Metabase»
Metabase написан на Clojure и крутится на JVM, поэтому холодный старт — это не секунды, а десятки секунд, иногда больше минуты на слабом CPU. Первое, что нужно сделать при подозрении на проблему — не убивать контейнер раньше времени, а посмотреть логи:
docker logs -f metabase
Если в логах тишина и процесс просто «висит» — это чаще всего нехватка памяти: JVM пытается выделить heap, но упирается в лимит контейнера, и ядро линукса убивает процесс через OOM killer, не оставляя внятной ошибки в логе приложения. Проверить факт OOM-убийства:
dmesg -T | grep -i "killed process"
Если видите там java — дело в памяти, а не в конфигурации. Второй частый случай — контейнер запущен без переменной JAVA_TIMEZONE или с неправильной базой данных приложения (об этом ниже), и Metabase зависает на миграциях схемы. В этом случае в логах будет что-то про Liquibase — это нормально, просто ждите: на первом старте с внешней Postgres миграции могут идти пару минут.
Минимальный рабочий docker-compose.yml для проверки, что базовая связка вообще жива:
services:
metabase:
image: metabase/metabase:latest
container_name: metabase
restart: unless-stopped
ports:
- "3000:3000"
environment:
MB_DB_TYPE: postgres
MB_DB_DBNAME: metabase
MB_DB_PORT: 5432
MB_DB_USER: metabase
MB_DB_PASS: ${MB_DB_PASS}
MB_DB_HOST: postgres
depends_on:
- postgres
deploy:
resources:
limits:
memory: 2g
postgres:
image: postgres:16
container_name: metabase-postgres
restart: unless-stopped
environment:
POSTGRES_USER: metabase
POSTGRES_DB: metabase
POSTGRES_PASSWORD: ${MB_DB_PASS}
volumes:
- metabase-pg-data:/var/lib/postgresql/data
volumes:
metabase-pg-data:
Обратите внимание на deploy.resources.limits.memory — без явного лимита Docker Compose его не применяет через docker-compose up без Swarm, поэтому на практике лимит памяти лучше задавать через mem_limit: 2g в самом сервисе, если вы не используете Swarm-стек.
Нехватка памяти: почему Metabase требует больше RAM, чем кажется
JVM по умолчанию резервирует heap как долю от доступной памяти контейнера — обычно около четверти видимой RAM, если явно не указан -Xmx. На сервере с 1 ГБ RAM это означает, что Metabase получит около 250 МБ heap, а самому приложению для комфортной работы с парой источников данных и несколькими одновременными дашбордами нужно заметно больше. Итог — либо OOM-убийство, либо мучительные подвисания интерфейса под нагрузкой.
Ориентировочные требования (именно ориентир, у вас может отличаться в зависимости от числа источников данных и сложности запросов):
| Сценарий | RAM для Metabase | RAM для встроенной Postgres | Итого рекомендуется |
|---|---|---|---|
| Личный проект, 1-2 источника данных | 1-1.5 ГБ | 0.5 ГБ | 2 ГБ |
| Команда до 10 человек, несколько источников | 2-3 ГБ | 1 ГБ | 4 ГБ |
| Продакшн-аналитика, много одновременных дашбордов | 4 ГБ+ | 1-2 ГБ | 6-8 ГБ |
Явно ограничить и одновременно гарантировать heap для JVM внутри Metabase можно через переменную JAVA_OPTS:
environment:
JAVA_OPTS: "-Xmx2g -Xms1g"
Если сервер слабый и апгрейд физической памяти пока не вариант, временная мера — своп. Он не заменит RAM для JVM (свопинг heap сильно бьёт по производительности сборщика мусора), но спасает от жёсткого OOM-килла в моменты пиков. Как правильно настроить своп под сервер — отдельная тема, разобрана в статье про настройку swap на Ubuntu 24.04. Но это костыль: правильное решение — сервер с запасом памяти под JVM, а не своп под боевую аналитику.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверПотеря настроек и дашбордов после перезапуска или обновления образа
Классическая ошибка — поднять Metabase командой docker run без volume или с базой H2 «по умолчанию» для теста, а потом обнаружить, что после docker compose down или обновления образа все дашборды, пользователи и подключения к источникам данных исчезли.
Дело в том, что Metabase по умолчанию хранит свою собственную конфигурацию (не аналитические данные — только настройки, дашборды, пользователей) во встроенной базе H2 внутри контейнера. Если volume для этого файла не примонтирован, при пересоздании контейнера всё стирается. Проверить, где физически лежит база:
docker exec metabase env | grep MB_DB
Если MB_DB_TYPE не установлен — вы на H2, и это нужно исправить. Два рабочих варианта:
- Смонтировать volume для H2 (быстро, но не рекомендуется для прод-нагрузки — H2 не любит параллельный доступ и хуже переживает сбои):
volumes:
- metabase-data:/metabase-data
environment:
MB_DB_FILE: /metabase-data/metabase.db
- Перейти на внешнюю Postgres (правильный путь, показан в конфиге выше). Миграция с H2 на Postgres делается штатным способом Metabase — через экспорт/импорт настроек в интерфейсе (Admin → Troubleshooting → в новых версиях есть встроенный мастер миграции) либо через официальную утилиту
load-from-h2. Перед любой миграцией обязательно снимите бэкап файла H2 — команда ниже сохранит копию на хосте:
docker cp metabase:/metabase-data/metabase.db.mv.db ./metabase-backup-$(date +%F).mv.db
Если уже используете внешнюю Postgres — не забывайте про регулярный бэкап и её самой, это критичные данные ваших дашбордов, а не только аналитические выборки. Общие принципы бэкапа Postgres в контейнере разобраны в статье про частые ошибки бэкапа MySQL на сервере — логика с dump'ами и ротацией схожая, разница в конкретных командах.
Подключение к источникам данных: тайм-ауты и ошибки доступа
Вторая по частоте боль — Metabase видит свою собственную базу настроек, но не может подключиться к базе данных, которую вы пытаетесь анализировать. Здесь почти всегда одна из трёх причин.
Сетевая изоляция Docker. Если аналитическая база крутится в отдельном docker-compose стеке или просто на хосте, а Metabase — в своём контейнере, они по умолчанию не видят друг друга. Решения:
- Подключить оба сервиса к общей внешней сети Docker:
networks:
shared-net:
external: true
- Либо указывать в качестве хоста базы данных не
localhost, аhost.docker.internal(на Linux нужно дополнительно прописатьextra_hosts):
extra_hosts:
- "host.docker.internal:host-gateway"
Firewall или security group закрывают порт. Если база на другом сервере — проверьте, что порт (5432 для Postgres, 3306 для MySQL) открыт именно для IP вашего сервера с Metabase, а не для всего интернета — это одновременно и вопрос безопасности.
sudo ufw allow from <IP_сервера_metabase> to any port 5432
SSL-требования базы. Managed-базы данных (RDS, Cloud SQL и подобные) часто требуют SSL-соединение. Metabase поддерживает это в настройках подключения источника данных — там есть отдельные поля для SSL-режима, их нужно включить явно, иначе получите тайм-аут или отказ соединения без внятного текста ошибки.
Медленные дашборды и запросы, которые «вешают» интерфейс
Когда Metabase подключена к боевой базе напрямую, тяжёлый дашборд с десятком карточек означает десяток запросов к продакшн-базе почти одновременно. Если это та же база, что обслуживает ваше приложение, аналитика начинает конкурировать с продакшном за ресурсы — и тормозит и то, и другое.
Практические меры:
- Кэширование результатов запросов. В Admin → Performance можно включить кэш на уровне отдельных вопросов/дашбордов с TTL — для дашбордов, где не нужны данные посекундно, это резко снижает нагрузку на базу.
- Отдельная read-реплика для аналитики. Если у вас Postgres с настроенной репликацией, логично пускать Metabase именно на реплику, а не на мастер. Про подводные камни репликации Postgres — в статье про частые ошибки репликации PostgreSQL.
- Материализованные представления или отдельная BI-схема для тяжёлых агрегаций, которые пересчитываются по расписанию, а не при каждом открытии дашборда.
- Индексы под конкретные фильтры дашбордов — если пользователи регулярно фильтруют по дате и статусу, а индекса под эту пару колонок нет, каждый такой запрос — full scan таблицы.
Если тюнинг самой Postgres тоже давно откладывался — общий подход к параметрам shared_buffers, work_mem и подобным разобран в статье про тюнинг PostgreSQL на сервере.
Metabase недоступен снаружи или падает SSL
Порт 3000 по умолчанию открыт наружу, если вы просто пробросили его в docker-compose — это неудобно (нет HTTPS) и небезопасно (никакой аутентификации на уровне сети, кроме собственного логина Metabase). Правильный путь — реверс-прокси перед контейнером.
Пример блока для Nginx с проксированием на локальный контейнер:
server {
listen 443 ssl http2;
server_name analytics.example.com;
ssl_certificate /etc/letsencrypt/live/analytics.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/analytics.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $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;
# Metabase использует WebSocket для некоторых live-обновлений
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Если сертификат не выпускается — почти всегда дело в том, что DNS-запись ещё не указывает на сервер, либо порт 80 занят другим сервисом и ACME-челлендж не проходит. Если предпочитаете автоматический SSL без ручной возни с certbot — присмотритесь к Caddy, сравнение подходов есть в статье Caddy или Nginx: что выбрать для сервера.
Отдельно закройте порт 3000 для внешнего доступа на firewall, чтобы обход через прокси нельзя было пропустить:
sudo ufw deny 3000
sudo ufw allow 443
Обновление Metabase без риска всё сломать
Metabase выпускает релизы часто, и соблазн держать тег latest велик — но именно это чаще всего приводит к неожиданным сюрпризам после автоматического пересоздания контейнера (например, systemd-таймером или Watchtower). Правильная практика:
- Фиксируйте конкретную версию образа:
metabase/metabase:v0.51.x, а неlatest. - Перед обновлением снимите бэкап базы приложения (Postgres, как описано выше — обычным
pg_dump). - Обновляйте на копии/staging-окружении, если Metabase критична для команды — миграции схемы между мажорными версиями иногда занимают время и в редких случаях требуют внимания к логам.
- Читайте changelog конкретной версии — иногда меняется поведение прав доступа или деприкейтятся старые типы визуализаций.
Откат на предыдущую версию образа безопасен только если вы не успели прогнать миграции новой схемы через боевую базу — поэтому бэкап перед обновлением не формальность, а единственный путь назад.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Сколько RAM реально нужно для Metabase на небольшой команде?
Для команды до 10 человек с несколькими источниками данных комфортно работает связка на 4 ГБ RAM (2-3 ГБ под саму Metabase плюс отдельно память под Postgres). Меньше — работает, но с риском OOM в пиковые моменты.
Можно ли использовать SQLite или H2 в проде вместо Postgres?
Технически да для собственной базы настроек Metabase, но это не рекомендуется для команды больше пары человек — H2 плохо переживает параллельный доступ и сбои. Для аналитической базы, которую вы визуализируете, использовать SQLite тоже можно, но её тоже стоит бэкапить отдельно.
Почему после обновления образа пропали кастомные визуализации или интеграции?
Проверьте, не был ли контейнер пересоздан без смонтированного volume для базы настроек (см. раздел про H2 выше) — это самая частая причина потери данных при обновлении.
Нужен ли отдельный сервер под Metabase или можно на том же, где крутится приложение?
Можно на том же, если ресурсов с запасом, но тяжёлые дашборды создают всплески нагрузки на CPU и память в моменты формирования отчётов — если приложение чувствительно к задержкам, лучше вынести аналитику на отдельный VPS.
Как понять, что причина падения — именно память, а не баг?
Команда dmesg -T | grep -i "killed process" покажет, убивал ли ядро процесс Java по OOM. Если да — решение не в конфигурации Metabase, а в увеличении памяти сервера или явном ограничении -Xmx.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →