MAATRIX / Блог / Apache Superset в Docker Compose: готовый файл

Apache Superset в Docker Compose: готовый файл

MAATRIX

Tableau стоит по подписке за пользователя, а бесплатные BI-инструменты часто упираются в потолок либо по визуализации, либо по объёму данных. Apache Superset — промышленный BI поверх практически любой SQL-базы, с богатым набором графиков и без лицензионных платежей: платите только за сервер. Но развернуть его правильно — не то же самое, что docker run с одним контейнером: Superset тянет за собой PostgreSQL, Redis и Celery-воркеры, и без них часть функций либо не работает, либо падает под нагрузкой. Ниже — рабочий docker-compose.yml со всеми этими частями, а не урезанный демо-вариант.

Обсудить статью, задать вопрос или начать новую тему

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

Перейти в сообщество →

Что такое Superset и когда он нужен

Apache Superset — open-source BI-платформа, изначально написанная в Airbnb и переданная в Apache Software Foundation. Python/Flask-приложение с фронтендом на React, которое умеет:

  • подключаться почти к любой базе через SQLAlchemy-драйверы: PostgreSQL, MySQL, ClickHouse, BigQuery, Trino и десятки других;
  • строить дашборды из готовых типов графиков (более 40 визуализаций) через drag-and-drop конструктор, плюс SQL Lab с автодополнением для тех, кто пишет запросы сам;
  • разграничивать доступ по ролям (Admin, Alpha, Gamma) и по строкам данных (Row Level Security);
  • отправлять алерты и отчёты по расписанию на email или в Slack при выполнении условия на данных.

По функциональности Superset ближе к Tableau, чем к более лёгким инструментам — платите вы не деньгами, а временем на настройку. Если нужен BI, который менеджер поднимет за час без разработчика, присмотритесь к Metabase в Docker Compose. Superset оправдан, когда дашбордов и источников много, нужна тонкая настройка прав или специфичные визуализации.

Сама база под аналитикой имеет значение не меньше, чем BI-слой сверху — на миллионах строк обычный PostgreSQL начинает упираться в агрегации, и стоит присмотреться к колоночным СУБД: разбор в статье ClickHouse или PostgreSQL для аналитики — что выбрать.

Минимум для работы — 2 vCPU и 4 ГБ RAM, но это впритык: веб-процесс, PostgreSQL, Redis и хотя бы один Celery-воркер вместе съедают половину этой памяти в простое. Для нескольких активных пользователей и SQL Lab закладывайтесь на 4 vCPU и 8 ГБ.

Готовый docker-compose.yml для Superset

Структура каталога:

superset/
├── docker-compose.yml
├── .env
├── superset_config.py
└── data/
    ├── postgres/
    └── redis/

.env:

POSTGRES_USER=superset
POSTGRES_PASSWORD=change_me_strong_password
POSTGRES_DB=superset
SUPERSET_SECRET_KEY=замените_на_случайную_строку_42+_символов
TZ=Europe/Moscow

Ключ сгенерируйте один раз и не меняйте — на нём держатся подписанные сессионные куки и шифрование сохранённых паролей к источникам данных:

openssl rand -base64 42

superset_config.py — обязательный файл, без него Superset либо не стартует, либо работает с настройками по умолчанию, непригодными для прода:

import os

SECRET_KEY = os.environ.get("SUPERSET_SECRET_KEY")

SQLALCHEMY_DATABASE_URI = (
    f"postgresql+psycopg2://{os.environ['POSTGRES_USER']}:"
    f"{os.environ['POSTGRES_PASSWORD']}@superset-db:5432/{os.environ['POSTGRES_DB']}"
)

REDIS_HOST, REDIS_PORT = "superset-redis", 6379

CACHE_CONFIG = {
    "CACHE_TYPE": "RedisCache",
    "CACHE_DEFAULT_TIMEOUT": 300,
    "CACHE_KEY_PREFIX": "superset_",
    "CACHE_REDIS_HOST": REDIS_HOST,
    "CACHE_REDIS_PORT": REDIS_PORT,
    "CACHE_REDIS_DB": 1,
}
DATA_CACHE_CONFIG = CACHE_CONFIG

class CeleryConfig:
    broker_url = f"redis://{REDIS_HOST}:{REDIS_PORT}/0"
    result_backend = f"redis://{REDIS_HOST}:{REDIS_PORT}/0"
    worker_prefetch_multiplier = 1
    task_acks_late = True

CELERY_CONFIG = CeleryConfig
FEATURE_FLAGS = {"ALERT_REPORTS": True}

docker-compose.yml:

services:
  superset-db:
    image: postgres:16-alpine
    container_name: superset-db
    restart: unless-stopped
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
    volumes:
      - ./data/postgres:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks: [superset-net]

  superset-redis:
    image: redis:7-alpine
    container_name: superset-redis
    restart: unless-stopped
    volumes:
      - ./data/redis:/data
    networks: [superset-net]

  superset:
    image: apache/superset:4.0.2
    container_name: superset
    restart: unless-stopped
    depends_on:
      superset-db: {condition: service_healthy}
      superset-redis: {condition: service_started}
    environment: &superset-env
      SUPERSET_SECRET_KEY: ${SUPERSET_SECRET_KEY}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
      SUPERSET_CONFIG_PATH: /app/pythonpath/superset_config.py
      TZ: ${TZ}
    volumes: &superset-vol
      - ./superset_config.py:/app/pythonpath/superset_config.py:ro
    ports:
      - "127.0.0.1:8088:8088"
    healthcheck:
      test: ["CMD-SHELL", "curl -sf http://localhost:8088/health || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 5
      start_period: 60s
    networks: [superset-net]

  superset-worker:
    image: apache/superset:4.0.2
    container_name: superset-worker
    restart: unless-stopped
    command: celery --app=superset.tasks.celery_app:app worker --pool=prefork -O fair -c 2
    depends_on: [superset]
    environment: *superset-env
    volumes: *superset-vol
    networks: [superset-net]

  superset-worker-beat:
    image: apache/superset:4.0.2
    container_name: superset-worker-beat
    restart: unless-stopped
    command: celery --app=superset.tasks.celery_app:app beat --pidfile /tmp/celerybeat.pid
    depends_on: [superset]
    environment: *superset-env
    volumes: *superset-vol
    networks: [superset-net]

networks:
  superset-net:
    driver: bridge

Версия 4.0.2 зафиксирована сознательно — минорные релизы меняют поведение конкретных чартов, обновление стоит проверять на тестовом стенде. superset-worker-beat нужен только для Alerts & Reports — если функция не нужна, сервис можно убрать.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Инициализация после первого запуска

В отличие от многих BI, у Superset нет мастера настройки через веб-интерфейс — админ и схема базы создаются командами внутри контейнера, один раз после первого старта.

docker compose up -d
docker compose logs -f superset

docker exec -it superset superset db upgrade

docker exec -it superset superset fab create-admin \
  --username admin --firstname Admin --lastname Admin \
  --email admin@example.com --password change_me_strong_password

docker exec -it superset superset init

db upgrade накатывает миграции схемы, fab create-admin создаёт первого пользователя (без него в интерфейс не зайти), superset init создаёт роли по умолчанию (Admin, Alpha, Gamma, Public) и права к ним. После этого интерфейс доступен на http://<ip-сервера>:8088 с заданным логином. Смените пароль через Settings → Reset My Password и заведите пользователей с ролями Alpha/Gamma — работать всей командой под общим Admin-аккаунтом не стоит.

PostgreSQL и Redis: зачем каждый нужен

PostgreSQL хранит метаданные — определения дашбордов, чартов, подключений, пользователей и прав. Это не та база, что вы анализируете: источники подключаются отдельно и могут быть любыми. Если PostgreSQL на сервере уже используется под другие проекты, для Superset разумно завести отдельную базу на существующем инстансе — установка с нуля описана в статье PostgreSQL на Ubuntu 24.04: пошаговая установка.

Redis закрывает две роли: кэш результатов запросов и брокер сообщений Celery. Без него часть функций либо не работает, либо блокирует веб-процесс:

ФункцияБез Redis/CeleryС Redis/Celery
Обычные дашбордыКаждый раз бьют в источникОтвет из кэша по таймауту
Тяжёлые запросы в SQL LabБлокируют веб-воркерАсинхронная очередь
Alerts & ReportsНе работаютРаботают через worker-beat
Экспорт больших дашбордовОграничен таймаутом HTTPАсинхронно, без таймаута

Для небольшой команды без алертов можно обойтись одним superset-worker без worker-beat. Полностью убирать Redis не стоит даже на маленькой инсталляции — без кэша каждое открытие дашборда заново бьёт в источник, и это первое узкое место при росте числа пользователей.

Reverse-proxy и HTTPS

Superset передаёт в интерфейсе пароли к базам данных — отдавать это на голом HTTP нельзя. Проще всего Traefik или Nginx Proxy Manager с автосертификатами Let's Encrypt; сравнение — в статье Traefik или Nginx Proxy Manager — что выбрать для сервера.

Если Traefik уже развёрнут отдельным стеком с сетью proxy, добавьте сервису superset лейблы вместо публикации порта:

  superset:
    ports: []
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.superset.rule=Host(`bi.example.com`)"
      - "traefik.http.routers.superset.entrypoints=websecure"
      - "traefik.http.routers.superset.tls.certresolver=letsencrypt"
      - "traefik.http.services.superset.loadbalancer.server.port=8088"
    networks: [superset-net, proxy]

networks:
  superset-net: {driver: bridge}
  proxy: {external: true}

Дополнительно выставьте ENABLE_PROXY_FIX = True в superset_config.py — иначе Superset не разберёт заголовки X-Forwarded-* и будет формировать ссылки в email-уведомлениях с localhost:8088 вместо реального домена.

Подключение источников и ресурсы

Источники добавляются через Settings → Database Connections. Для баз в соседних Docker-сетях хостом подключения указывается имя контейнера. Для прод-баз создавайте отдельного read-only пользователя, а не подключайтесь под аккаунтом приложения:

CREATE USER superset_ro WITH PASSWORD 'strong_password';
GRANT CONNECT ON DATABASE app_production TO superset_ro;
GRANT USAGE ON SCHEMA public TO superset_ro;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO superset_ro;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO superset_ro;

Так аналитик через SQL Lab не сможет случайно изменить данные, а тяжёлый SELECT не встанет в очередь блокировок с продовыми транзакциями. Часть коннекторов (BigQuery, Trino, ClickHouse) требует пакета поверх базового образа — apache/superset включает только PostgreSQL, MySQL и SQLite «из коробки», остальное ставится через pip install в кастомном образе, который указывается вместо apache/superset:4.0.2 сразу во всех сервисах — драйвер нужен и веб-процессу, и воркерам.

Веб-процесс в простое держится в пределах нескольких сотен мегабайт, но каждый Celery-воркер — отдельный Python-процесс. На общем сервере стоит ограничить контейнеры лимитами, чтобы всплеск нагрузки не забрал память у соседей — подход разобран в статье Docker: лимиты CPU и памяти для контейнера. Ориентировочно (без гарантии для вашей нагрузки) 2 воркера из конфига рассчитаны на 1–2 ГБ RAM на процесс.

Бэкап и обновление

Бэкапить нужно базу метаданных PostgreSQL — данные источников бэкапятся отдельно на своей стороне.

docker exec superset-db pg_dump -U superset superset | gzip > superset_backup_$(date +%F).sql.gz

Cron с недельной историей копий:

0 3 * * * docker exec superset-db pg_dump -U superset superset | gzip > /backup/superset_$(date +\%F).sql.gz
find /backup -name "superset_*.sql.gz" -mtime +7 -delete

Восстановление:

gunzip -c superset_backup_2026-08-20.sql.gz | docker exec -i superset-db psql -U superset -d superset

Обновление — смена тега образа во всех сервисах и прогон миграций:

docker compose pull
docker compose up -d
docker exec -it superset superset db upgrade
docker compose restart superset-worker superset-worker-beat

Перед мажорным обновлением (например, 3.x → 4.x) снимите свежий дамп базы метаданных — миграции необратимы, а в changelog между мажорными версиями периодически встречаются breaking changes для кастомных плагинов и визуализаций.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Чем Superset принципиально отличается от Metabase?

Superset тяжелее в развёртывании (нужны PostgreSQL, Redis и Celery отдельно), но даёт больше визуализаций и гибкую систему прав вплоть до Row Level Security. Metabase проще освоить не-разработчику. Выбор — вопрос того, что важнее: скорость запуска или глубина возможностей.

Можно ли обойтись без Redis и Celery-воркера?

Технически запустится и без них, но отключится кэширование чартов, а Alerts & Reports не будут работать вовсе. Для чего-то, кроме разового теста, Redis стоит оставить.

Нужен ли отдельный сервер под Superset?

Можно на том же, где крутится приложение, если ресурсов хватает с запасом. Важно, чтобы Celery-воркеры с тяжёлыми запросами не конкурировали за память и I/O с продовой базой в пиковую нагрузку.

Как перенести Superset на другой сервер?

Перенести volume с PostgreSQL, superset_config.py и .env с тем же SUPERSET_SECRET_KEY — без него подключения к источникам не расшифруются.

Обсудить статью, задать вопрос или начать новую тему

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

Перейти в сообщество →