From 78cf7b5fae544e5e18aecc80026e7d27288f008b Mon Sep 17 00:00:00 2001 From: Dmitry Dementev Date: Mon, 19 Oct 2026 09:26:12 +0200 Subject: [PATCH] fix(stack): use pinned MinIO image with registry fallback --- .env.example | 9 +++++ README.md | 9 +++-- START_HERE.md | 15 ++++++-- docker-compose.yml | 13 +++---- docs/maintainer_guide.md | 4 +-- docs/mentor_notes.md | 4 +-- docs/network_access.md | 74 ++++++++++++++++++++++++++++++++++++++++ docs/stack_reference.md | 26 +++++++++----- minio/Dockerfile | 46 ------------------------- tests/browser_ide.cjs | 4 ++- tests/browser_ide.sh | 1 + 11 files changed, 132 insertions(+), 73 deletions(-) create mode 100644 .env.example create mode 100644 docs/network_access.md delete mode 100644 minio/Dockerfile diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..34fea71 --- /dev/null +++ b/.env.example @@ -0,0 +1,9 @@ +# Копировать в .env необязательно: это значения по умолчанию. +# Если .env уже есть, добавь нужную настройку в него, сохранив остальные. + +# GHCR — основной источник MinIO. Резерв того же автора и digest: docker.io. +MINIO_REGISTRY=ghcr.io + +# На Linux при необходимости укажи свой UID и GID (команды: id -u; id -g). +NB_UID=1000 +NB_GID=100 diff --git a/README.md b/README.md index 025ab45..ee63f4a 100755 --- a/README.md +++ b/README.md @@ -17,7 +17,8 @@ ## Стек -Всё работает локально в Docker. Никаких облаков, внешних зависимостей и регистраций. +Всё работает локально в Docker. Для первой сборки и скачивания учебных данных +нужен интернет; облачный аккаунт не требуется. ```mermaid graph TB @@ -69,13 +70,15 @@ graph TB Краткий запуск из корня репозитория: ```bash +docker compose pull minio minio-init postgres trino docker compose build docker compose up -d docker compose ps ``` -MinIO собирается из закреплённых официальных исходников; первая сборка занимает -несколько дополнительных минут. Подробности — в [техническом reference](./docs/stack_reference.md#minio). +MinIO скачивается готовым из GHCR, его версия и digest закреплены. Если какой-то +источник недоступен из твоей сети, начни с +[инструкции по доступу к репозиториям](./docs/network_access.md). После старта: diff --git a/START_HERE.md b/START_HERE.md index efb3906..325fbe7 100644 --- a/START_HERE.md +++ b/START_HERE.md @@ -30,6 +30,11 @@ Python, Java, Jupyter и расширения VS Code устанавливаются при сборке Docker-образов. На хосте не нужно создавать venv или устанавливать Python-пакеты. +Для первой сборки нужен доступ к внешним репозиториям. Если ты работаешь из РФ +или сети с ограничениями, при ошибке скачивания используй +[инструкцию по доступу к репозиториям](./docs/network_access.md): в ней есть +резервный источник MinIO и отдельные шаги для Docker и сборки зависимостей. + ## Порты стенда | Сервис | Адрес | Зачем нужен | @@ -57,14 +62,16 @@ export NB_UID=$(id -u) NB_GID=$(id -g) Для Docker Desktop на macOS и Windows обычно подходят значения по умолчанию. -### 1. Собрать образы +### 1. Скачать готовые образы и собрать окружение ```bash +docker compose pull minio minio-init postgres trino docker compose build ``` -Первая сборка скачивает зависимости и компилирует MinIO из закреплённых исходников. -На это может уйти несколько минут. Версии описаны в [техническом reference](./docs/stack_reference.md#minio). +Первая команда проверяет загрузку готовых сервисов до сборки окружения. +MinIO уже собран; для Spark, Jupyter и IDE первая сборка скачивает зависимости +и может занять несколько минут. Повторная сборка использует кэш Docker. ### 2. Поднять стенд @@ -170,6 +177,8 @@ docker compose logs -f ide ### Типовые первые проверки +- Ошибка скачивания образа или зависимостей: найди имя недоступного источника + в сообщении и открой [диагностику сети](./docs/network_access.md). - `Spark UI` не открывается: проверь `docker compose ps` и логи `spark-master`. - `Trino UI` не открывается: проверь `docker compose ps` и логи `trino`. - `JupyterLab` не открывается: проверь `docker compose ps` и логи `jupyter`. diff --git a/docker-compose.yml b/docker-compose.yml index 278504c..22b7bdd 100755 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -121,9 +121,8 @@ services: - ./spark/spark-defaults.conf:/opt/spark/conf/spark-defaults.conf:ro minio: - build: - context: ./minio - target: minio + # Один и тот же образ опубликован автором в GHCR и Docker Hub. + image: &minio-image ${MINIO_REGISTRY:-ghcr.io}/coollabsio/minio:RELEASE.2025-04-22T22-12-26Z@sha256:a4938f37f1be1841b8e7b627ad0207b265345fd0d063e42d7410c78af0e63e68 container_name: minio hostname: minio networks: @@ -139,9 +138,7 @@ services: - minio-data:/data minio-init: - build: - context: ./minio - target: mc + image: *minio-image container_name: minio-init hostname: minio-init networks: @@ -149,13 +146,13 @@ services: depends_on: - minio entrypoint: > - /bin/sh -c " + /bin/sh -ec " echo 'Waiting for MinIO...'; until mc alias set minio http://minio:9000 minioadmin minioadmin 2>/dev/null; do sleep 1; done; echo 'MinIO is up, creating bucket...'; - mc mb -p minio/lakehouse || true; + mc mb --ignore-existing minio/lakehouse; echo 'Bucket lakehouse is ready'; exit 0; " diff --git a/docs/maintainer_guide.md b/docs/maintainer_guide.md index 5d17951..ca011c1 100644 --- a/docs/maintainer_guide.md +++ b/docs/maintainer_guide.md @@ -17,7 +17,7 @@ | Зона | Где лежит | Назначение | | --- | --- | --- | -| Runtime / stand | `docker-compose.yml`, `spark/`, `trino/`, `jupyter/`, `ide/`, `minio/` | Топология сервисов, образы, конфиги, порты | +| Runtime / stand | `docker-compose.yml`, `spark/`, `trino/`, `jupyter/`, `ide/` | Топология сервисов, образы, конфиги, порты | | Onboarding | `README.md`, `START_HERE.md` | Вход в репозиторий и первый пользовательский маршрут | | Runtime reference | `docs/stack_reference.md` | Технические детали стенда: порты, доступ, команды, smoke-тесты | | Course definition | `docs/course_prd.md`, `docs/course_program.md` | Границы курса, learning outcomes, структура модулей | @@ -31,7 +31,7 @@ | Файл или каталог | За что отвечает | Что не стоит туда складывать | | --- | --- | --- | | `docker-compose.yml` | Реальный состав сервисов, контейнеров, сетей, портов и зависимостей | Учебные пояснения, которые не нужны для запуска | -| `spark/`, `trino/`, `jupyter/`, `ide/`, `minio/` | Конкретные runtime-конфиги и образы | Описание программы курса | +| `spark/`, `trino/`, `jupyter/`, `ide/` | Конкретные runtime-конфиги и образы | Описание программы курса | | `README.md` | Верхнеуровневое объяснение репозитория, архитектуры и точек входа | Пошаговый student onboarding во всех деталях и low-level runtime reference | | `START_HERE.md` | Первый маршрут студента: prerequisites, запуск, первые UI, первый ноутбук, базовая диагностика | Полный PRD курса или подробный бэклог модулей | | `docs/stack_reference.md` | Технический reference стенда: сервисы, порты, доступ, reset, smoke-тесты | Роль основного onboarding-документа или описание всей программы курса | diff --git a/docs/mentor_notes.md b/docs/mentor_notes.md index 45eb719..2bafb70 100644 --- a/docs/mentor_notes.md +++ b/docs/mentor_notes.md @@ -34,8 +34,8 @@ ### Модуль 1. Вход в стенд -- **Docker не хватает ресурсов.** Стенд требует ~4-6 ГБ RAM. На машинах с 8 ГБ бывают проблемы. Решение: увеличить лимиты Docker Desktop или закрыть лишние приложения. -- **Порты заняты.** 8080, 8888, 9000 — популярные порты. `docker compose ps` покажет, какой сервис не стартовал. Решение: остановить конфликтующий процесс или (крайний вариант) поменять порт в `docker-compose.yml`. +- **Docker не хватает ресурсов.** Сверься с [требованиями в START_HERE](../START_HERE.md#prerequisites). Проверь отдельно память компьютера и лимит памяти Docker Desktop/WSL2: контейнерам может быть доступна лишь часть RAM хоста. +- **Порты заняты.** Проверь 8080, 8889, 9000 и остальные [порты стенда](../START_HERE.md#порты-стенда). `docker compose ps` покажет, какой сервис не стартовал. Решение: остановить конфликтующий процесс или (крайний вариант) поменять порт в `docker-compose.yml`. - **Студент не читает `START_HERE.md`.** Начинает с ноутбуков до поднятия стенда. Направь обратно к стартовому документу. ### Модуль 2. Ментальная модель diff --git a/docs/network_access.md b/docs/network_access.md new file mode 100644 index 0000000..a47b947 --- /dev/null +++ b/docs/network_access.md @@ -0,0 +1,74 @@ +# Если образы или зависимости не скачиваются + +Доступность репозиториев зависит от сети и провайдера, в том числе в РФ. +GHCR выбран основным источником MinIO, чтобы его загрузка не зависела от Docker +Hub. Это не гарантия доступности без VPN у каждого провайдера: у стенда остаются +другие внешние зависимости. Для первой сборки и скачивания датасета нужен интернет. + +## Сначала найди источник ошибки + +Запускай команды в терминале хоста, из корня репозитория: + +```bash +docker compose pull minio minio-init postgres trino +docker compose --progress plain build +``` + +Если первая команда завершилась с ошибкой, сначала реши проблему загрузки образа. +Если ошибка возникла во второй, найди имя сервиса и адрес, с которого скачивался +файл. Открывающийся в браузере сайт ещё не подтверждает доступ из Docker. + +| Где возникла ошибка | Что скачивается | Что проверить | +| --- | --- | --- | +| `ghcr.io` при загрузке `minio` | Готовые MinIO и `mc` | Резервный источник ниже | +| `docker.io`, `registry-1.docker.io`, `auth.docker.io` | PostgreSQL, Trino, базовый Spark; резерв MinIO | Доступ Docker к Docker Hub и настройки прокси | +| Ubuntu archive, PyPI, Maven Central при сборке `spark` или `jupyter` | Системные пакеты, Python-пакеты и JAR | Доступ к зависимостям из сборки | +| GitHub Releases, Open VSX при сборке `ide` | code-server и расширения | Доступ к зависимостям из сборки | + +## Резервный источник MinIO + +Автор образа публикует его в двух местах: GHCR и Docker Hub. В обоих закреплён +один digest, поэтому смена registry не меняет версию или содержимое образа. +Ссылка на сборку и версия приведены в [техническом reference](./stack_reference.md#minio). + +Если GHCR недоступен, создай файл `.env` в корне репозитория и добавь строку: + +```dotenv +MINIO_REGISTRY=docker.io +``` + +Если файл уже существует, измени только эту настройку. Другие значения, например +`NB_UID` и `NB_GID`, сохрани. Затем повтори: + +```bash +docker compose pull minio minio-init +``` + +Дальше используй обычные команды из [START_HERE](../START_HERE.md#быстрый-запуск). +Для возврата к основному источнику установи `MINIO_REGISTRY=ghcr.io`. +Оба источника публичные; регистрация для скачивания MinIO не требуется. +`.env.example` содержит пример настроек, а `.env` исключён из Git. + +## Если недоступны другие источники + +Переключение MinIO не меняет источник PostgreSQL, Trino, Spark или зависимостей +сборки. Если в твоей сети нужен VPN или HTTP-прокси, важно, чтобы им мог +пользоваться Docker, а не только браузер. + +- **Docker Desktop:** настрой прокси в разделе **Settings → Resources → Proxies**. + См. [официальную инструкцию](https://docs.docker.com/desktop/settings-and-maintenance/settings/#proxies). +- **Docker Engine на Linux:** скачиванием образов занимается демон Docker. + Для него есть [отдельная настройка прокси](https://docs.docker.com/engine/daemon/proxy/). +- **Команды внутри сборки:** `apt`, `pip`, `curl` и установка расширений требуют + доступа из build-контейнера. Docker описывает + [настройки прокси для сборок](https://docs.docker.com/engine/cli/proxy/#build-with-a-proxy-configuration) + отдельно от настроек демона. Прокси на `localhost` хоста не обязательно + доступен как `localhost` внутри контейнера. + +Ошибка `429` обычно означает лимит запросов, а `401`/`403` может быть связана +с доступом к registry. Сам по себе этот код не доказывает блокировку по стране. +Не меняй версии образов и не удаляй данные стенда для исправления сетевой ошибки. + +Если нужна помощь, передай ментору ОС, вывод `docker compose version`, команду, +имя сервиса и фрагмент ошибки с адресом источника. Пароли и адреса прокси +с учётными данными в сообщение не добавляй. diff --git a/docs/stack_reference.md b/docs/stack_reference.md index 55ded82..105ff17 100644 --- a/docs/stack_reference.md +++ b/docs/stack_reference.md @@ -107,13 +107,20 @@ SHOW TABLES FROM lakehouse.default; - логин: `minioadmin` - пароль: `minioadmin` -Стенд собирает MinIO Server `RELEASE.2024-10-02T17-50-41Z` и `mc` -`RELEASE.2024-06-24T19-40-33Z` из официальных исходников. Коммиты и SHA-256 архивов -зафиксированы в `minio/Dockerfile`. Готовые образы этих версий в Docker Hub и Quay -больше не загружаются; бинарный архив `dl.min.io` также недоступен. -Первая сборка компилирует Go-код и занимает несколько дополнительных минут. -Версии сохранены ради совместимости с курсом и его MinIO Console; они больше -не получают обновлений upstream и не предназначены для production. +Стенд использует готовый образ `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`. @@ -210,7 +217,7 @@ JupyterLab остаётся запасным интерфейсом. Он ред | `jupyter/Dockerfile` | образ JupyterLab на базе Spark | | `ide/Dockerfile` | code-server и расширения на базе образа Jupyter | | `ide/lakehouse.code-workspace` | папки рабочей области и настройки Python | -| `minio/Dockerfile` | сборка закреплённых исходников MinIO Server и `mc` | +| `docs/network_access.md` | источники образов и зависимостей, резервный registry и диагностика сети | ## Smoke-тесты @@ -230,6 +237,9 @@ bash tests/browser_ide.sh путь печатается перед запуском. Docker Desktop этим скриптом не проверяется: он использует Linux host networking. +Для проверки отдельного стенда можно задать `COMPOSE_FILE` и `IDE_URL`; по +умолчанию тест использует текущий Compose-проект и `http://localhost:8889`. + ### 1. Проверка, что Spark-кластер жив ```bash diff --git a/minio/Dockerfile b/minio/Dockerfile deleted file mode 100644 index 3f09863..0000000 --- a/minio/Dockerfile +++ /dev/null @@ -1,46 +0,0 @@ -# Сохраняем версии стенда после удаления исторических бинарных образов upstream. -FROM golang:1.22.8-bookworm AS build-base -ENV CGO_ENABLED=0 GOMAXPROCS=2 -WORKDIR /src - -FROM build-base AS build-minio -# RELEASE.2024-10-02T17-50-41Z -RUN curl -fL --retry 3 \ - https://codeload.github.com/minio/minio/tar.gz/ded0b19d97bb9f73f4d78382eb131ff80003e272 \ - -o /tmp/source.tar.gz \ - && echo '1619e07c52b91611f399f5415cdf5aa96d3beac418bb909db9d7b6f86bbcfb6f /tmp/source.tar.gz' | sha256sum -c - \ - && tar -xzf /tmp/source.tar.gz --strip-components=1 \ - && rm /tmp/source.tar.gz -RUN go build -p 2 -trimpath -ldflags="-s -w \ - -X github.com/minio/minio/cmd.Version=2024-10-02T17:50:41Z \ - -X github.com/minio/minio/cmd.ReleaseTag=RELEASE.2024-10-02T17-50-41Z \ - -X github.com/minio/minio/cmd.CommitID=ded0b19d97bb9f73f4d78382eb131ff80003e272" \ - -o /out/minio . - -FROM build-base AS build-mc -# RELEASE.2024-06-24T19-40-33Z -RUN curl -fL --retry 3 \ - https://codeload.github.com/minio/mc/tar.gz/3548007d5bd1ba8e2ed98f35d95c4776dd9a7ff9 \ - -o /tmp/source.tar.gz \ - && echo '760ac5bf7eb2e44a67a7dd1e5508853e54c10ca75f2b2f2385c5c227042436c5 /tmp/source.tar.gz' | sha256sum -c - \ - && tar -xzf /tmp/source.tar.gz --strip-components=1 \ - && rm /tmp/source.tar.gz -RUN go build -p 2 -trimpath -ldflags="-s -w \ - -X github.com/minio/mc/cmd.Version=2024-06-24T19:40:33Z \ - -X github.com/minio/mc/cmd.ReleaseTag=RELEASE.2024-06-24T19-40-33Z \ - -X github.com/minio/mc/cmd.CommitID=3548007d5bd1ba8e2ed98f35d95c4776dd9a7ff9" \ - -o /out/mc . - -FROM debian:bookworm-slim AS runtime -COPY --from=build-base /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ - -FROM runtime AS minio -COPY --from=build-minio /out/minio /usr/local/bin/minio -COPY --from=build-minio /src/LICENSE /usr/share/doc/minio/LICENSE -EXPOSE 9000 9001 -ENTRYPOINT ["minio"] - -FROM runtime AS mc -COPY --from=build-mc /out/mc /usr/local/bin/mc -COPY --from=build-mc /src/LICENSE /usr/share/doc/mc/LICENSE -ENTRYPOINT ["mc"] diff --git a/tests/browser_ide.cjs b/tests/browser_ide.cjs index 7a8c210..42a1784 100644 --- a/tests/browser_ide.cjs +++ b/tests/browser_ide.cjs @@ -51,7 +51,9 @@ async function checkOutput(page) { } }); try { - await page.goto('http://localhost:8889', { waitUntil: 'domcontentloaded' }); + await page.goto(process.env.IDE_URL || 'http://localhost:8889', { + waitUntil: 'domcontentloaded', + }); assert(await page.evaluate(() => isSecureContext && 'serviceWorker' in navigator)); await page.getByRole('tree', { name: 'Files Explorer' }).waitFor(); // Баннер появляется позже Explorer; при повторном тесте доверие уже сохранено. diff --git a/tests/browser_ide.sh b/tests/browser_ide.sh index 0a88df3..ccdb3f6 100644 --- a/tests/browser_ide.sh +++ b/tests/browser_ide.sh @@ -9,6 +9,7 @@ docker compose exec -T ide cp /opt/work/01_environment_and_smoke_test.ipynb \ /tmp/lakehouse-browser-smoke.ipynb docker run --rm --network host --shm-size=1g \ + -e IDE_URL="${IDE_URL:-http://localhost:8889}" \ -v "$PWD:/repo:ro" -v "$artifact_dir:/artifacts" \ mcr.microsoft.com/playwright:v1.56.1-noble \ bash -c 'npm install --prefix /tmp/browser-test --no-audit --no-fund playwright@1.56.1 >/dev/null &&