Learning Platform
Глоссарий Troubleshooting
Урок 16.03 · 20 мин
Начальный
Documentationdbt docsCatalogManifestLineageUI

dbt docs generate и serve

В предыдущих уроках мы писали description и doc blocks. Теперь — как превратить их в работающий UI, где аналитики ищут модели, читают descriptions, смотрят DAG-граф зависимостей.

dbt не имеет «облачного UI» из коробки — это локальная статическая веб-страница, которую генерирует команда dbt docs generate, а потом раздаёт dbt docs serve (или хостит на любом static-сервере).

В этом уроке — что генерится, что в UI, типичные паттерны деплоя.


Две команды: generate и serve

dbt docs generate    # генерит документацию
dbt docs serve       # запускает локальный веб-сервер для просмотра

Это две независимые операции. generate собирает данные, serve показывает их в браузере.

В CI/CD типично: dbt docs generate -> push артефактов в S3 / GitHub Pages / Netlify. dbt docs serve — для локальной разработки.


Что делает dbt docs generate

Под капотом — три шага:

dbt CLI
Project files
Warehouse
target/
1. Parse projectmanifest.json2. Query schemascatalog.json3. Combine into static site

В итоге в папке target/ появляются файлы:

target/
  manifest.json     ← структура проекта (models, dependencies, descriptions)
  catalog.json      ← actual schemas из warehouse
  run_results.json  ← результаты последнего run/test (если был)
  graph.gpickle     ← Python-pickle графа (для internal dbt операций)
  partial_parse.msgpack  ← cache парсинга
  compiled/         ← скомпилированный SQL каждой модели
  run/              ← SQL запросы, которые выполнялись
  index.html        ← статический UI (это что показывает dbt docs serve)

Размер target/ обычно — десятки МБ для проекта на 100 моделей. Для огромных проектов (1000+ моделей) — может быть 100+ МБ.


Что делает dbt docs serve

После dbt docs generate запускаете:

dbt docs serve
# Serving docs at 0.0.0.0:8080
# Press Ctrl+C to exit.

Открывается локальный HTTP-сервер на порту 8080. Заходите в браузере на http://localhost:8080 — видите UI.

Под капотом — это обычный static file server. Раздаёт файлы из target/. Никакой динамики, никаких запросов в warehouse — всё уже в manifest.json и catalog.json.

Поэтому dbt docs serve можно заменить на любой static-сервер:

cd target && python -m http.server 8080
# или
cd target && npx serve

Это значит — легко хостится на GitHub Pages / Netlify / S3 + CloudFront / любом nginx.


Структура UI

При открытии UI:

Структура UI dbt docs

Что на странице модели

Открыв fct_orders в UI, видим:

  1. Header: имя модели, тип (model / seed / snapshot / source), путь к файлу.
  2. Description: rendered markdown из YAML / doc block.
  3. Columns: таблица с колонками — name, type, description, tests.
  4. Details (collapsible): config (materialized, schema), tags, meta.
  5. Code: исходный SQL (raw) + compiled SQL.
  6. Tests: список тестов на этой модели.
  7. Lineage graph: визуализация DAG — кто upstream, кто downstream.

Это must-have для аналитика: открыл модель -> за 30 секунд понял что это, какие колонки, откуда приходит, кто использует.


Lineage graph — самая ценная часть

Граф зависимостей — главная фича dbt docs. Кнопка справа внизу View Lineage Graph.

В графе:

  • Зелёные узлы — sources.
  • Синие узлы — models.
  • Жёлтые узлы — seeds.
  • Фиолетовые узлы — snapshots.
  • Розовые узлы — exposures.

Линии — ref() / source() зависимости. Стрелка от A к B = “A -> B” = “B зависит от A”.

Селекторы графа:

  • +model — модель и все upstream.
  • model+ — модель и все downstream.
  • +model+ — модель + upstream + downstream (full lineage).
  • Несколько селекторов — пересечение / объединение.

Это критический инструмент:

  • Хотите понять «откуда приходит fct_orders» -> +fct_orders -> видите 5 staging-моделей и source.
  • Хотите понять «что сломается, если изменю stg_jaffle__customers» -> stg_jaffle__customers+ -> видите 10 downstream-моделей и 2 exposure’а.
  • Onboarding нового member’а: показываете +main_dashboard_mart+ — он за минуту видит весь поток.

Откуда берётся каждая часть UI

Элемент UIИсточник
Имя и путь моделиmanifest.json (parsed from project files)
Descriptionmanifest.json (из YAML descriptions + doc blocks)
Columns + typescatalog.json (queried from warehouse)
Column descriptionsmanifest.json (из YAML descriptions)
Testsmanifest.json (parsed from YAML + tests/)
Lineage graphmanifest.json (parsed ref/source dependencies)
Compiled SQLtarget/compiled/*.sql (from dbt parse)
Raw SQLmanifest.json (model body)

Поэтому: если column не имеет description в YAML — UI покажет колонку без описания (имя, тип из catalog, но пусто справа). Если column есть в YAML, но нет в warehouse (модель ещё не была material-ed) — UI покажет description, но не покажет тип.

Для полного UI нужны и dbt run (чтобы материализовать) + dbt docs generate (чтобы сгенерить catalog).


Типичный workflow

В реальной разработке:

# 1. Изменили модель + добавили описание в YAML
vim models/marts/fct_orders.sql
vim models/marts/_marts__models.yml

# 2. Материализовали модель
dbt run --select fct_orders

# 3. Сгенерили документацию (читает обновлённый manifest + catalog)
dbt docs generate

# 4. Открыли UI и проверили
dbt docs serve
# -> http://localhost:8080 -> найти fct_orders -> проверить description, lineage

В CI:

# В pipeline:
dbt deps                     # пакеты
dbt build                    # все модели + тесты
dbt docs generate            # документация
# -> push target/ в S3 / GitHub Pages

Документация деплоится автоматически после каждого merge в main. Аналитики всегда видят актуальную версию.


catalog.json — что внутри

catalog.json — это state warehouse. Для каждой модели:

{
  "nodes": {
    "model.jaffle_shop.fct_orders": {
      "metadata": {
        "type": "BASE TABLE",
        "schema": "marts",
        "name": "fct_orders",
        "database": "jaffle_shop_db"
      },
      "columns": {
        "order_id": {
          "type": "INTEGER",
          "index": 1,
          "name": "order_id",
          "comment": null
        },
        "amount_usd": {
          "type": "DECIMAL(10,2)",
          "index": 2,
          "name": "amount_usd"
        }
      },
      "stats": {
        "row_count": { "value": 50432 },
        "bytes": { "value": 1572864 }
      }
    }
  }
}

Откуда:

  • metadata — из INFORMATION_SCHEMA warehouse.
  • columns — из SELECT * LIMIT 0 или INFORMATION_SCHEMA.
  • stats — warehouse-specific (DuckDB / Postgres имеют свои источники).

Если запустить dbt docs generate без dbt run — модели нет в warehouse, catalog будет пустой для этих моделей. UI покажет descriptions из manifest, но без типов колонок.

TIP

dbt docs generate --no-compile — пропускает dbt parse и dbt compile, использует существующий manifest. Быстрее, если только обновляете catalog. Но для production — лучше делайте full generate.


manifest.json — структура проекта

manifest.json — это structure dbt-проекта. Содержит все nodes:

{
  "nodes": {
    "model.jaffle_shop.fct_orders": {
      "name": "fct_orders",
      "resource_type": "model",
      "package_name": "jaffle_shop",
      "path": "marts/core/fct_orders.sql",
      "description": "**Grain**: один заказ ...",
      "depends_on": {
        "nodes": [
          "model.jaffle_shop.stg_jaffle__orders",
          "model.jaffle_shop.dim_customers"
        ]
      },
      "columns": {
        "order_id": {
          "name": "order_id",
          "description": "Primary key",
          "data_tests": ["not_null", "unique"]
        }
      },
      "config": {
        "materialized": "table",
        "schema": "marts",
        "tags": ["finance"]
      }
    }
  },
  "sources": { ... },
  "macros": { ... },
  "docs": { ... },
  "exposures": { ... },
  "metadata": {
    "dbt_version": "1.10.2",
    "generated_at": "2026-05-19T10:23:45Z",
    "project_name": "jaffle_shop"
  }
}

Это источник правды для UI. Все descriptions, dependencies, configs, tests — отсюда.

manifest.json также используется для state comparison в CLI (dbt run --state ./prod-manifest --select state:modified).


Хостинг документации

Production-проекты обычно деплоят docs на shared URL:

ХостингКак
GitHub PagesPush target/ в gh-pages branch. Free, простой.
NetlifyПодключить repo, build command = dbt docs generate, publish dir = target/.
S3 + CloudFrontaws s3 sync target/ s3://bucket/. Кастомный домен. Стандарт для enterprise.
dbt CloudЕсли вы на dbt Cloud — есть встроенный hosting через “Documentation tab”.
Internal nginxСкопировать target/ на сервер, отдавать через nginx.

GitHub Pages — самый простой старт для junior проекта.

WARNING

Не публикуйте dbt docs открыто в интернет, если в descriptions есть бизнес-чувствительная информация (формулы метрик, размеры таблиц, имена клиентов в descriptions). Используйте authentication (Netlify Identity, CloudFront signed URLs, basic auth nginx).


Что часто ломается

Типичные проблемы с dbt docs

Попробуй сам

В вашем dbt-проекте:

dbt run            # материализовать все модели
dbt docs generate  # сгенерить документацию
dbt docs serve     # запустить локальный сервер

Откройте http://localhost:8080. Поэкспериментируйте:

  1. Поиск: найдите модель по части имени.
  2. Открыть модель: посмотрите description, columns, code (raw vs compiled).
  3. Lineage graph: нажмите кнопку Lineage. Выделите модель в центре. Видите upstream / downstream.
  4. Селекторы графа: введите +fct_orders (для примера) — увидите всех предков.
  5. Найти source: откройте source jaffle. Посмотрите freshness section (если настроили loaded_at_field).

Бонус: запустите dbt run без какой-то модели (dbt run --exclude fct_orders). Запустите dbt docs generate. В UI откройте fct_orders — что показывается? Description есть, но columns без types — потому что таблицы в warehouse нет.


Ключевые выводы

  1. dbt docs generate собирает manifest.json (структура) и catalog.json (state warehouse).
  2. dbt docs serve — простой static HTTP-сервер для target/index.html.
  3. UI состоит из: sidebar (project hierarchy), main area (model details: description, columns, code, tests), lineage graph.
  4. Lineage graph — самая ценная часть. Селекторы +model, model+, +model+ для навигации.
  5. Descriptions в UI отрисовываются как rendered markdown (из YAML + doc blocks).
  6. catalog.json пустой для моделей, которые не были dbt run. UI покажет description, но без типов колонок.
  7. Хостинг production: GitHub Pages / Netlify / S3 + CloudFront / nginx. Документация — статический сайт.
  8. CI pipeline: после dbt build запускайте dbt docs generate и пушите target/ на хостинг.
dbt Cloud Explorer: управляемый lineage UI
Проверка знанийKnowledge check
После `dbt docs serve` аналитик жалуется: 'для всех staging-моделей колонки показываются без типов'. В чём проблема?
ОтветAnswer
Проблема в **catalog.json**. Чтобы UI показывал типы колонок, dbt должен **прочитать их из warehouse** через INFORMATION_SCHEMA. Если модель не была материализована (`dbt run` не запускался для неё) — таблица не существует, catalog для неё пустой.\n\nРешение:\n\n1. `dbt run --select staging` — материализовать все staging-модели.\n2. `dbt docs generate` — пересобрать catalog.json теперь, когда модели существуют.\n3. `dbt docs serve` — открыть UI снова.\n\nЕщё причины:\n\n- **Staging как view, и они dropped.** Если staging материализован как view, и dbt run --full-refresh уничтожил их, но catalog ещё не обновлён — те же симптомы. Решение: rerun docs generate.\n- **Wrong target.** dbt run в target=dev, dbt docs generate в target=prod. catalog читает из prod, где моделей нет. Проверьте `dbt docs generate --target dev`.\n- **Permissions.** dbt user не имеет SELECT на INFORMATION_SCHEMA. Редкая проблема в DuckDB, частая в Snowflake с rigid permissions.\n\nПомнить: catalog = warehouse state, manifest = project structure. Если в UI есть имя но нет типа — нужно material-ize модель.
Проверка знанийKnowledge check
Команда хочет, чтобы docs автоматически деплоились после каждого merge в main. Какие шаги в CI pipeline?
ОтветAnswer
Pipeline (на примере GitHub Actions):\n\n```yaml\nname: Deploy dbt docs\n\non:\n push:\n branches: [main]\n\njobs:\n docs:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n - name: Setup Python\n uses: actions/setup-python@v4\n with: { python-version: '3.11' }\n - name: Install dbt\n run: pip install dbt-core==1.10.2 dbt-duckdb==1.10.1\n - name: dbt deps\n run: dbt deps\n - name: dbt build (creates fresh tables)\n run: dbt build --target prod\n - name: dbt docs generate\n run: dbt docs generate --target prod\n - name: Deploy to GitHub Pages\n uses: peaceiris/actions-gh-pages@v3\n with:\n github_token: ${{ secrets.GITHUB_TOKEN }}\n publish_dir: ./target\n```\n\nЧто делает:\n\n1. **Checkout** репозитория.\n2. **Install dbt** нужной версии.\n3. **dbt deps** для подгрузки packages.\n4. **dbt build** — материализует модели (нужно для catalog с типами).\n5. **dbt docs generate** — собирает manifest + catalog.\n6. **Push target/** в gh-pages branch — статический сайт на `https://org.github.io/repo/`.\n\nНа Netlify проще — подключаешь репо, указываешь build command `dbt deps && dbt build && dbt docs generate` и publish dir `target`.\n\n**Важно**: для CI нужны warehouse credentials (профили dbt в `profiles.yml`). Обычно — через env vars (`DBT_DUCKDB_PATH` или `SNOWFLAKE_PASSWORD`).

Проверьте понимание

Результат: 0 из 0
Аналитический
Вопрос 1 из 5. Аналитик: 'В dbt docs все staging-модели показываются БЕЗ типов колонок (имя есть, тип пустой)'. Почему?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 4