Дашборд на Streamlit, Dash или Metabase собирается за вечер, а проблема начинается на следующий день: показать его коллегам нечем. Ссылка вида localhost:8501 открывается только на вашем ноутбуке, скриншоты в рабочем чате надоедают к третьему дню, а идеи с корпоративным VPN, пробросом порта и вечно включённым ноутбуком разбиваются о первый же созвон. Дашборд — обычное веб-приложение, поэтому ему нужен хостинг: загружаете код на Dockbox, платформа собирает проект, запускает его и отдаёт публичную HTTPS-ссылку, которую можно вставить в рабочий чат. Разбираем, что предусмотреть до загрузки — порт, источник данных, доступ, память.
Почему дашборд остаётся на localhost
Локальный адрес никому не виден. 127.0.0.1 означает «эта машина»: у коллеги по той же ссылке откроется его собственный компьютер, а не ваш график.
VPN как транспорт. Поднять всех коллег в корпоративную сеть ради пары диаграмм не проходит у безопасников — и почти никогда не работает, если у людей разные операционные системы.
Проброс порта. Нужен белый IP, настройка роутера и объяснение, почему ваш ноутбук вообще доступен из интернета. Ноутбук на ночь. Открыли крышку — дашборд вернулся, закрыли — ссылка мертва, а кеш расчётов потерян.
Разница между Streamlit, Dash и готовым BI-инструментом не в языке: платформа определяет стек по файлам проекта (requirements.txt, package.json) и запускает всё в Docker-контейнере.
Порт — из переменной окружения, адрес — 0.0.0.0
Порт задаёт платформа через переменную PORT. Число, вписанное в код или в конфиг фреймворка, — главная причина, по которой дашборд собирается без ошибок, а ссылка остаётся пустой. Второе условие — слушать 0.0.0.0: приложение, привязанное к localhost, доступно только самому себе.
Для Streamlit настройки передаются командой запуска, а не файлом:
streamlit run app.py --server.address=0.0.0.0 --server.port=$PORT --server.headless=true
У Dash адрес и порт указываются в коде:
import os
if __name__ == "__main__":
app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 8050)))
Gradio читает те же две настройки через launch(server_name="0.0.0.0", server_port=int(os.environ["PORT"])). Горячую перезагрузку (debug=True, --server.runOnSave) в продакшене не включайте.
Откуда дашборд берёт данные
Файл в проекте — это снимок. CSV или Excel рядом с кодом уезжает на сервер вместе с архивом и меняется только при следующей публикации. Для справочника регионов — нормально, для ежедневных цифр — нет.
Живые числа читайте из базы. Управляемого сервиса баз на платформе нет, поэтому вариантов два: подключить внешнюю базу по строке соединения или поднять свою рядом с дашбордом — отдельным сервисом в собственном docker-compose, где приложение и PostgreSQL живут в одном проекте. Строку соединения держите в секретах, а не в коде:
import os
DB_URL = os.environ["DATABASE_URL"]
Агрегации считайте в SQL, а не в Python: базе это дешевле, а дашборду останется нарисовать результат.
Что дашборд пишет на диск — в папку /data
Всё, что создано рядом с кодом, при следующей публикации пересоздаётся с нуля. Кеш тяжёлых расчётов, предрасчитанные витрины, выгруженные отчёты и настройки, которые сохранил зритель, кладите в постоянную папку /data: её содержимое переживает и обновление кода, и перезапуск, а файлы видно на вкладке Data в панели, откуда их можно скачать, загрузить или удалить.
CACHE_DIR = "/data/cache"
REPORTS_DIR = "/data/reports"
Если база — файл SQLite, ей там же и место, путь вида /data/app.db. У проекта со своим docker-compose папки /data нет: постоянное хранилище в таких проектах задаётся именованными томами в вашем файле.
Пароль внутрь приложения, секреты — в переменные
Ссылка публичная: кто её знает, тот и откроет. Проверять доступ нужно внутри приложения — форма входа или общий пароль до того, как показан первый график. Готовые BI-инструменты вроде Metabase закрыты своим логином из коробки, а в Streamlit и Dash достаточно небольшой надстройки:
import os
import streamlit as st
password = st.text_input("Пароль", type="password")
if password != os.environ["DASH_PASSWORD"]:
st.stop()
Пароль держите в секретах проекта: платформа запрашивает такие значения при настройке и передаёт их в контейнер в зашифрованном виде, поэтому в архиве и в репозитории они не появляются.
Обновление кода не меняет ссылку
Проект попадает на платформу архивом (ZIP, RAR, 7z, tar) или импортом репозитория GitHub, включая приватный. Не кладите в архив venv и node_modules — зависимости всё равно ставятся при сборке. Дальше платформа собирает образ, запускает контейнер и выдаёт HTTPS-адрес, а статус сборки и логи в панели обновляются в реальном времени, поэтому ошибка видна сразу и с понятной причиной, а не как пустая страница. Новая версия уезжает тем же путём, а адрес остаётся прежним: правки кода не ломают ссылку в вики и в закладках коллег.
Сколько памяти нужно дашборду
Дашборд держит данные в памяти и считает их, как правило, через pandas. Streamlit выполняет скрипт заново на каждую сессию зрителя — десять открытых вкладок это десять копий вашего DataFrame. Отсюда правило: тяжёлые выборки сворачивайте в SQL и кешируйте результат, а не отдавайте в интерфейс миллион строк.
Starter (990 ₽/мес) — 1 vCPU и 2 ГБ RAM: этого хватает дашборду, который читает агрегаты из базы. Metabase или Superset вместе с базой рядом заметно тяжелее, такой проект стоит смотреть на Pro (2 490 ₽/мес). Контейнеры работают постоянно: дашборд не засыпает и отвечает сразу, без «прогрева» первой загрузки, а упавший контейнер платформа перезапускает сама.
Сколько это стоит
Starter — 990 ₽/мес, первый месяц бесплатно. 1 vCPU, 2 ГБ RAM, один проект — для внутреннего дашборда этого достаточно.
Pro — 2 490 ₽/мес — больше ресурсов и до пяти проектов, если рядом живут база и BI-инструмент.
Team — 4 990 ₽/мес — запас ресурсов и SLA для команды.
Цены — в рублях, отдельных счетов за трафик и сборки нет, а свой сервер арендовать не нужно: nginx, сертификаты и автозапуск платформа берёт на себя. Попробуйте на Dockbox — первый месяц на Starter бесплатный.
Частые вопросы
Дашборд собрался, но ссылка пустая. Что смотреть?
Почти всегда — адрес и порт: приложение должно слушать 0.0.0.0 и порт из переменной PORT, а не 127.0.0.1 и число из кода. Вторая причина — падение при старте из-за отсутствующей библиотеки или недоступной базы; текст ошибки виден в логах панели.
Как сделать, чтобы цифры на дашборде обновлялись сами?
Читайте свежие данные из базы на каждой загрузке, а не из файла в архиве. Отдельного планировщика на платформе нет, поэтому периодический пересчёт пишите в код: цикл с паузой или библиотека вроде APScheduler. Результат складывайте в базу или в /data, чтобы он пережил публикацию.
Можно ли пустить на дашборд только свою команду?
Пользователей и прав на стороне платформы нет — ссылка публичная, поэтому проверку доступа делайте внутри приложения, формой входа или общим паролем. Секреты держите в переменных окружения: они передаются в контейнер зашифрованными и не попадают ни в архив, ни в репозиторий.
Потянет ли платформа готовый BI-инструмент вроде Metabase или Superset?
Да, если в проекте есть свой Dockerfile или docker-compose: по нему можно поднять несколько связанных сервисов — например BI-приложение и базу рядом. Такая сборка тяжелее небольшого Streamlit-дашборда, а постоянное хранилище в ней задаётся именованными томами в вашем файле: папки /data у таких проектов нет.
Нужен ли свой сервер или VPS?
Нет. Dockbox разворачивает проект на своих серверах в Docker-контейнере: не нужно арендовать VPS, ставить nginx, настраивать systemd и продлевать сертификаты — всё это делает платформа.