# Технический reference стенда Этот документ описывает сам стенд как runtime-среду: сервисы, порты, доступ, основные команды и smoke-тесты. Если нужен первый student onboarding, используй [START_HERE.md](../START_HERE.md). Если нужна программа курса, используй [course_program.md](./course_program.md). ## Состав сервисов | Сервис | Контейнер | Порт на хосте | Назначение | | --- | --- | --- | --- | | Spark master | `spark-master` | `7077`, `8080` | мастер Spark и его UI | | Spark worker 1 | `spark-worker-1` | `8081` | первый worker Spark | | Spark worker 2 | `spark-worker-2` | `8082` | второй worker Spark | | Trino | `trino` | `8090` | SQL engine и Web UI | | MinIO API | `minio` | `9000` | S3-compatible endpoint | | MinIO Console | `minio` | `9001` | веб-консоль бакетов и объектов | | PostgreSQL | `postgres-iceberg` | `5432` | JDBC-каталог Iceberg | | VS Code в браузере (code-server) | `ide` | `8889` | основной интерфейс для ноутбуков и терминала | | JupyterLab | `jupyter` | `8888` | запасной интерфейс для тех же ноутбуков | ## Основные команды Все команды выполняются в терминале хоста из корня репозитория. Для первого запуска и настройки прав используй [START_HERE](../START_HERE.md), для продолжения работы — [памятку учащегося](./study_workflow.md). ### Сборка и запуск ```bash docker compose pull minio minio-init postgres trino docker compose build docker compose up -d docker compose ps -a ``` ### Логи ```bash docker compose logs -f spark-master docker compose logs -f trino docker compose logs -f minio docker compose logs -f jupyter docker compose logs -f ide ``` ### Остановка и reset | Действие | Команда | Что происходит с данными | | --- | --- | --- | | Пауза до следующего занятия | `docker compose stop` | Контейнеры остановлены, файлы и volumes сохранены | | Продолжение | `docker compose up -d` | Сервисы запускаются с прежними данными | | Удаление контейнеров и сети | `docker compose down` | Volumes и файлы на хосте сохраняются, состояние внутри удаленных контейнеров теряется | | Полный сброс учебных данных | См. [отдельную инструкцию](./study_workflow.md#начать-с-чистых-данных) | Удаляются MinIO volume и каталог PostgreSQL | Переменные Python и живые Spark-сессии после остановки нужно создать заново. ## Ресурсы и проверенная среда Актуальный бюджет для учащегося приведен в [системных требованиях](../START_HERE.md#системные-требования). Он учитывает одновременную работу двух Spark worker-ов, драйвера в IDE, Trino, MinIO и PostgreSQL. У каждого worker-а в Compose указаны 2 CPU и 2 ГБ для приложений Spark; это не предел потребления всей JVM или контейнера. Потребление при простое не показывает пик во время урока. Проверка 19 октября 2026 года: Linux x86_64, Docker Engine, 6 CPU и около 11,1 ГиБ памяти, видимых Docker. Выполнены первый ноутбук в Chromium и проверка Spark → Iceberg → Trino. Прогона всех восьми модулей с измерением пиков памяти и диска не было; минимальный объем RAM не установлен. Docker Desktop и ARM64 в этой проверке не запускались. Размеры локально собранных образов на этой машине: Spark — около 3,37 ГБ, Jupyter — 3,72 ГБ, IDE — 4,90 ГБ. Jupyter включает слои Spark, IDE включает слои Jupyter: складывать эти три числа для оценки места неправильно. IDE добавляет около 1,18 ГБ. IDE вместе с отдельными образами Trino, PostgreSQL и MinIO дает около 8,1 ГБ до учета кэша сборки, данных и особенностей хранилища Docker. Поэтому перед первой сборкой нужен запас места сверх размера готовых образов. ## Доступ к сервисам ### Spark - Master UI: `http://localhost:8080` - Worker UI: `http://localhost:8081` и `http://localhost:8082` - Адрес Spark master внутри сети Docker Compose: `spark://spark-master:7077` Адрес кластера (`spark.master`) и настройки доступа к Iceberg и MinIO заданы в [`spark/spark-defaults.conf`](../spark/spark-defaults.conf). Docker подключает этот файл к контейнеру Jupyter как `/opt/spark/conf/spark-defaults.conf`. При первом вызове `getOrCreate()` Spark читает настройки и создает сессию. Повторный вызов использует уже работающую сессию. Если изменил адрес кластера или настройки в файле, перезапусти ядро ноутбука и снова выполни ячейки с импортами и созданием сессии. Фактический master и имя приложения доступны через `spark.sparkContext.master` и `.appName`. Текущие SQL-настройки можно прочитать через `spark.conf.get(...)`. В Spark 3.5.1 `spark.sql.session.timeZone` меняется через `spark.conf.set(...)` без остановки сессии. Для нового имени приложения нужен новый SparkContext. Пример запуска smoke-скрипта: ```bash docker compose exec ide python3 /opt/src/spark/cluster_smoke.py ``` ### Trino - Web UI: `http://localhost:8090` CLI внутри контейнера: ```bash docker compose exec -it trino trino --catalog lakehouse ``` Примеры первых команд: ```sql SHOW CATALOGS; SHOW SCHEMAS FROM lakehouse; SHOW TABLES FROM lakehouse.default; ``` **Подключение через DBeaver:** - Host: `localhost`, Port: `8090`, Catalog: `lakehouse`, User: любая строка, Password: нет. - Driver: Trino (встроен в DBeaver). - Проверка: `SHOW SCHEMAS FROM lakehouse;`. ### MinIO - S3 endpoint: `http://localhost:9000` - Console: `http://localhost:9001` - логин: `minioadmin` - пароль: `minioadmin` Стенд использует готовый образ `coollabsio/minio:RELEASE.2025-04-22T22-12-26Z`. Это сторонняя [сборка из официальных исходников MinIO](https://github.com/coollabsio/minio), которая содержит сервер и клиент `mc` версии `RELEASE.2025-08-13T08-35-41Z`. Версия сервера предшествует [изменению встроенной консоли в мае 2025 года](https://github.com/minio/minio/releases/tag/RELEASE.2025-05-24T17-08-30Z). Образ подходит для локального курса; это историческая версия без текущих обновлений, не production-конфигурация. В Compose закреплён digest индекса для AMD64 и ARM64: `sha256:a4938f37f1be1841b8e7b627ad0207b265345fd0d063e42d7410c78af0e63e68`. Сервисы `minio` и `minio-init` используют один образ. Компиляция MinIO и установка Go не нужны. По умолчанию образ скачивается из GHCR без авторизации. Автор публикует тот же digest в Docker Hub; резервный источник выбирается через `MINIO_REGISTRY=docker.io` в `.env`. Подробности — в [инструкции по доступу к репозиториям](./network_access.md). Бакет `lakehouse` обычно создаётся автоматически контейнером `minio-init`. ### PostgreSQL Подключение с хоста: ```bash psql -h localhost -p 5432 -U iceberg -d iceberg ``` Служебные таблицы JDBC-каталога создаёт `iceberg-catalog-init`. Если нужен повторный запуск инициализации: ```bash docker compose run --rm iceberg-catalog-init ``` ### VS Code в браузере Открой `http://localhost:8889`. Сервис `ide` запускает code-server с установленными расширениями Python и Jupyter. Python, ipykernel, Java, PySpark и зависимости курса уже находятся в образе. Локальный Python или venv не нужен. В рабочей области доступны ноутбуки, примеры из `src/` и документация. Репозиторий смонтирован в `/opt/course` только для чтения, а его каталог `notebooks/` — для чтения и записи. Так относительные ссылки между документами и ноутбуками работают и внутри IDE. Пути `/opt/work`, `/opt/src`, `/opt/data` также доступны примерам курса. Открой `01_environment_and_smoke_test.ipynb`, нажми **Select Kernel → Python Environments** и выбери `/usr/bin/python3`. Это Python внутри контейнера IDE. Расширение Jupyter запускает ядро там же; адрес отдельного Jupyter Server вводить не требуется. Порт IDE опубликован только на `127.0.0.1`, без пароля, для одного пользователя. Открывай именно `localhost` или `127.0.0.1`: браузер считает их доверенным контекстом даже по HTTP. Notebook webview использует service worker; при обращении по обычному HTTP к IP сервера или имени в локальной сети этот механизм может быть недоступен. Это ограничение secure context, отдельное от CORS и XSRF. См. [secure contexts](https://developer.mozilla.org/en-US/docs/Web/Security/Defenses/Secure_Contexts) и [webviews в code-server](https://coder.com/docs/code-server/FAQ#why-do-web-views-not-work). Для стенда на удалённой машине используй SSH-туннель: ```bash ssh -N -L 8889:127.0.0.1:8889 user@host ``` Затем открой `http://localhost:8889` на своём компьютере. Прямой доступ по публичному адресу не входит в эту конфигурацию. Образы собираются в порядке `spark-master → jupyter → ide` через Compose `additional_contexts` (нужен Docker Compose 2.17+ и BuildKit). Версии code-server и расширений зафиксированы в `ide/Dockerfile`; расширения скачиваются при сборке. Автоматическое обновление расширений отключено, чтобы повторный запуск использовал проверенные версии. ### JupyterLab - адрес: `http://localhost:8888` - порт опубликован только на `127.0.0.1` хоста; - аутентификация и XSRF-проверка отключены для локального одно-пользовательского стенда; - через VS Code Remote-SSH используй `Existing Jupyter Server` с адресом `http://127.0.0.1:8888/` без token; - `./notebooks` смонтирован как `/opt/work` - `./src` смонтирован read-only как `/opt/src` - `./data` смонтирован read-only как `/opt/data` - `PYTHONPATH=/opt/src` JupyterLab остаётся запасным интерфейсом. Он редактирует те же файлы, но запускает отдельные ядра: переменные Python между IDE и JupyterLab не общие. Перед сменой интерфейса сохрани ноутбук и останови его ядро. Первый ноутбук курса: `notebooks/01_environment_and_smoke_test.ipynb`. Для Модуля 3 локально скачанный data bundle должен лежать на хосте в `./data/nyc_taxi` и будет доступен внутри Jupyter по пути `/opt/data/nyc_taxi`. ## Как связаны Spark, Trino, PostgreSQL и MinIO - `Spark` использует каталог `lakehouse` через `JdbcCatalog`. - `Trino` использует тот же каталог `lakehouse` через `iceberg.jdbc-catalog`. - метаданные таблиц лежат в `PostgreSQL`; - данные и metadata-файлы Iceberg лежат в `MinIO` в бакете `lakehouse`. Именно поэтому таблица, созданная в `Spark`, может читаться в `Trino` без копирования данных. ## Где лежат ключевые конфиги | Файл | Что задаёт | | --- | --- | | `docker-compose.yml` | состав сервисов, порты, volumes, init-контейнеры | | `spark/spark-defaults.conf` | Spark master, catalog `lakehouse`, `s3a`, Iceberg extensions | | `trino/catalog/lakehouse.properties` | каталог Trino `lakehouse`, JDBC и S3-доступ | | `spark/Dockerfile` | образ Spark с Iceberg, S3A и Python-зависимостями | | `jupyter/Dockerfile` | образ JupyterLab на базе Spark | | `ide/Dockerfile` | code-server и расширения на базе образа Jupyter | | `ide/lakehouse.code-workspace` | папки рабочей области и настройки Python | | `docs/network_access.md` | источники образов и зависимостей, резервный registry и диагностика сети | | `docs/study_workflow.md` | повседневная работа, сохранение состояния и диагностика ошибок | ## Smoke-тесты ### Браузерная IDE и Jupyter-ноутбук На Linux с Docker Engine, после запуска стенда: ```bash bash tests/browser_ide.sh ``` Проверка запускает Chromium в отдельном контейнере и проходит путь студента: доверие рабочей области → открытие копии Модуля 1 → выбор Python → Run All → вывод Spark в webview → сохранение → повторное открытие. Затем проверяет, что все кодовые ячейки выполнились без ошибок и результат сохранился. Исходный ноутбук не меняется. Скриншот остаётся в каталоге `/tmp/lakehouse-browser-check.*`, путь печатается перед запуском. Docker Desktop этим скриптом не проверяется: он использует Linux host networking. Для проверки отдельного стенда можно задать `COMPOSE_FILE` и `IDE_URL`; по умолчанию тест использует текущий Compose-проект и `http://localhost:8889`. ### 1. Проверка, что Spark-кластер жив ```bash docker compose exec ide python3 /opt/src/spark/cluster_smoke.py ``` ### 2. Проверка Spark -> Trino через общий каталог ```bash docker compose cp src/spark/iceberg_smoke.py spark-master:/tmp/ docker compose cp src/trino/iceberg_smoke.sql trino:/tmp/ docker compose exec spark-master /opt/spark/bin/spark-submit /tmp/iceberg_smoke.py docker compose exec trino trino --file /tmp/iceberg_smoke.sql ``` Ожидаемый результат: - в Spark создаётся `lakehouse.default.spark_trino_smoke`; - в Trino видна та же таблица; - выборка возвращает строку `1, from_spark`. Опциональная очистка: ```bash docker compose exec spark-master \ /opt/spark/bin/spark-sql -e "DROP TABLE IF EXISTS lakehouse.default.spark_trino_smoke" ``` ## Краткая шпаргалка ### Ключевые S3-пути курса | Путь | Назначение | | --- | --- | | `s3a://lakehouse/raw/nyc_taxi/` | raw-зона: исходные Parquet и CSV | | `s3a://lakehouse/warehouse/bronze/` | bronze-таблицы Iceberg | | `s3a://lakehouse/warehouse/silver/` | silver-таблицы Iceberg | ### Основные таблицы курса | Таблица | Создаётся в | | --- | --- | | `lakehouse.bronze.nyc_taxi_yellow` | Модуль 4 | | `lakehouse.bronze.taxi_zone_lookup` | Модуль 4 (самостоятельное задание) | | `lakehouse.silver.nyc_taxi_yellow` | Модуль 5 | ### Часто используемые Spark SQL ```sql -- Просмотр структуры каталога SHOW TABLES IN lakehouse.bronze; -- Метаданные Iceberg SELECT * FROM