MiniLake: SQL、Delta Lake、Sparkを備えたローカルDatabricks APIエミュレーター
MiniLake Is a Local Databricks API Emulator with SQL, Delta Lake and Spark (dmux.github.io)
要約
MiniLakeは、ローカル環境でDatabricks APIのエミュレーションを行うツールです。これにより、開発者はクラウドのアカウントやAPIキーなしで、実際のSQL、Delta Lake、Sparkジョブを実行できます。DuckDBやDockerなどのリアルなエンジンを使用し、開発やCI/CDの効率化に貢献します。
全文翻訳
ラップトップで動作するDatabricks API。
オープンソース · MIT · Python 3.11+ · Docker
MiniLakeは、実際のSQL、実際のDelta Lake、実際のSparkジョブ実行を備えたローカルのDatabricks APIエミュレーターです。databricks-sdk、Databricks CLI、Terraform、Asset Bundles、またはLLMエージェントをhttp://localhost:8000に向けさせることができます — アカウント不要、APIキー不要、クラウドの請求もありません。
$ pip install minilake && minilake --port 8000 PyPI
$ docker run -p 8000:8000 ghcr.io/dmux/minilake:latest GHCR
その後、組み込みのSQLワークスペースを表示するには http://localhost:8000/ui/ を開いてください。このイメージは実行時に何もダウンロードしません — エアギャップでも動作します。
[画像: MiniLake logo]
ドロップイン対応
databricks-sdk (Python) Databricks CLI Terraform provider Asset Bundles PySpark + Delta MCP agents
*30+***Unity CatalogからSCIMまで、Databricks APIグループをエミュレート
67MCPツール(LLMエージェント向け)、同じポートで提供
378+**実際のDatabricks SDKで実行されたテスト、モックではない
$0クラウド費用 — すべてがあなたのマシンで実行されます
何が得られるか
モックサーバーではありません。Databricks形状のAPIの背後にある実際のエンジンです。
偽のエンドポイントは壊れたコードを通過させます。MiniLakeはDuckDBでSQLを実行し、実際のDeltaファイルを書き込み、コンテナで実際のspark-submitジョブを実行します — だからローカルでのテストが成功すれば意味があります。
実際のUnity Catalog
カタログ、スキーマ、テーブル、ボリュームの完全なCRUD。各カタログは独自のDuckDBデータベースファイルであるため、catalog.schema.tableのアドレス指定はネイティブです — 正規表現による書き換えではありません。
実際の実行
実際に実行されるSQL
実際のDuckDBでのステートメント実行:INLINEおよびEXTERNAL_LINKSのディスポジション、JSON_ARRAY / ARROW_STREAM / CSVフォーマット、および真の列型を持つ結果マニフェスト。
実際の実行
実際のDelta Lakeファイル
EXTERNAL Deltaテーブルは、Parquetと_delta_log/の正規の組み合わせです。INSERT、UPDATE、DELETEは実際のSparkジョブにルーティングされ、読み取りはDuckDBのdelta_scan()を介して行われます。
実際のDelta
実際に実行されるジョブ
spark_python_taskは、兄弟コンテナでspark-submitを実行し、実際の標準出力を返します。実際のDAGスケジューリングはdepends_onとrun_ifを尊重し、並列で独立したブランチを持ちます。
実際のSpark
Spark用のUnity Catalogプロトコル
spark.table("cat.sch.tbl")は、公式のUCSingleCatalogコネクタを介してMiniLakeに対して解決されます — Sparkが実際のワークスペースと通信するのと同じプロトコルです。
ワイヤー互換
組み込みのSQLワークスペース
/uiにあるAthenaスタイルのエディター:カタログ認識補完を備えたMonaco、仮想化された結果グリッド、チャート、CSV/JSONエクスポート、保存されたクエリ、クエリ履歴 — そして埋め込みJupyterLab。
すぐに使える
Terraform & Asset Bundles
databricksプロバイダーをlocalhostに向けさせると、terraform applyで実際のカタログが作成されます。すべてのテスト実行で検証済み:実際のプロバイダーはapply、plan、destroyを通じて実行され、2回目のプランは空でなければなりません。databricks bundle deployとbundle runはエンドツーエンドで動作します — ジョブは実際に実行されます。
ワイヤー互換
エージェント用のMCPサーバー
/mcpには67のツール、8つのリソース、4つのプロンプトがあります — 5回の呼び出しシーケンスを1回にまとめるコンポジットや、エージェントがSpark SQLを書くのを止めるSQL方言リソースなどが含まれます。
実際の実行
CI向け設計
1回のPOST /_minilake/resetで、コンテナを再起動せずに各テストにクリーンなワークスペースを提供します。/health、/ready、/servicesがコントロールプレーンを完成させます。
テストフレンドリー
Workspace, DBFS, Files, Secrets
チャンクアップロードを備えたファイルベースのノートブックおよびファイルストレージ。Secretsは実際のCRUDであり、その値はジョブの環境内でのみ解決可能で、Databricksと全く同じです。
実際の実行
設計によるエアギャップ
DuckDBのdelta拡張機能とDelta / Unity CatalogのJARは、ビルド時に組み込まれています。イメージは実行時に何もダウンロードしません — docker run --network noneで証明できます。
オフライン対応
Databricks形状のエラー
失敗は{"error_code", "message"}として返されるため、SDKは通常の型付き例外を発生させます。範囲外のものは、説得力のある嘘の代わりに、大きな501 NOT_IMPLEMENTEDを返します。
ワイヤー互換
コード変更ゼロ
ホストを変更するだけ。それが移行です。
MiniLakeはワイヤー上でDatabricks REST APIを話すため、あなたが既に使っているすべてのクライアントはそのまま動作します — 同じ呼び出し、同じ応答形状、同じ型付きエラー。
- 任意のトークンが受け入れられます。 開発のためにサインアップ、PAT、OAuthのダンスは不要です。
- 型は往復します。
STRING、LONG、DECIMAL(10,2)、ARRAY<T>、MAP、STRUCTはDuckDBにマッピングされ、SDKのColumnInfoとして返されます。 - 物理的な真実が優先されます。 ファイルと一致しない宣言された列型は失われます。そのため、不一致は信じられるのではなく、可視化されます。
- 必要に応じて永続化されます。
MINILAKE_PERSIST=1はシャットダウン時に状態をスナップショットし、起動時に復元します。
quickstart.py
from databricks.sdk import WorkspaceClient
from databricks.sdk.service.catalog import ColumnInfo, TableType
# 本番環境と異なるのはこの1行だけ
w = WorkspaceClient(host="http://localhost:8000", token="dev")
w.catalogs.create(name="sales")
w.schemas.create(name="store", catalog_name="sales")
w.tables.create(
name="orders", catalog_name="sales", schema_name="store",
table_type=TableType.MANAGED,
data_source_format="DELTA", storage_location="/data/sales/store/orders",
columns=[
ColumnInfo(name="id", type_text="BIGINT"),
ColumnInfo(name="customer", type_text="STRING"),
ColumnInfo(name="amount", type_text="DECIMAL(10,2)"),
],
)
wh = w.warehouses.create(name="dev", cluster_size="Small")
w.statement_execution.execute_statement(
warehouse_id=wh.id,
statement="INSERT INTO sales.store.orders VALUES (1, 'Ana', 459.90)",
)
result = w.statement_execution.execute_statement(
warehouse_id=wh.id,
statement="SELECT customer, amount FROM sales.store.orders",
)
print(result.result.data_array) # [['Ana', '459.90']] — 実際に保存されています
仕組み
1つのプロセス。1つのポート。その下にリアルなエンジン。
FastAPIアプリケーションがDatabricks RESTサーフェス、Web UI、MCPエンドポイントをまとめて提供します。その背後にはDuckDB、ディスク上の実際のDeltaファイル、そしてSpark用のDockerがあります。
CLIENTS databricks-sdkWorkspaceClient (Python) Databricks CLIbundle deploy · bundle run Terraform providerapply · destroy PySpark / JupyterLabspark.table("cat.sch.tbl") LLM agentsModel Context Protocol Browser/ui のSQLワークスペース MINILAKE · ONE PROCESS MiniLake FastAPI · uvicorn · :8000 /api/2.0 · /api/2.1 Databricks REST surface /ui · /jupyter SQLワークスペース + notebooks /mcp エージェント用67ツール /_minilake/* health · ready · reset REAL ENGINES DuckDB 1カタログあたり1つのデータベースファイル Delta Lake on disk parquet +
_delta_log/
Docker → Apache Spark spark-submit, sibling container Sparkがファイルを書き込み — DuckDBが同じバイトを読み取る
LLMエージェント向け
エージェントに壊せないレイクハウスを与える。
Databricksワークスペースはエージェントが操作するには扱いにくいものです:有用なアクションはすべて4つの呼び出しの深さがあり、書かれるSQLの半分は方言が間違っており、失敗は静かです。MiniLakeのMCPサーバーはこれらのギャップを埋めます — そしてエージェントが間違えたときには何も費用がかかりません。
setup_fixture()カタログ + スキーマ + ウェアハウスを1回の冪等な呼び出しでseed_table()テーブル + 行、要求された通りの行describe_catalog_tree()数十回の呼び出しの代わりに階層全体run_python_script()ステージング、実際のSparkにサブミット、ポーリング、標準出力を返す
さらに8つのリソース — エージェントがDuckDBでSpark SQLを書くのを止めるSQL方言ガイドを含む — と、ルールを事前にロードする4つのプロンプトがあります。ツールはMiniLake独自のASGIスタックを通じて実行されるため、エージェントのエラーはSDKクライアントが見たであろうエラーと全く同じです。
登録して使用
# Claude Codeに登録するための1行
claude mcp add --transport http minilake http://localhost:8000/mcp
# その後、尋ねるだけです:
# "minilakeを使って、ordersテーブルがシードされたsalesカタログを作成し、合計金額を教えてください。"
# エージェントはこれを実行します — 3回の呼び出し、グルーコードなし:
# setup_fixture({"catalog": "sales", "schema": "store"})
# seed_table({"full_name": "sales.store.orders", ...})
# run_sql({"statement": "SELECT SUM(amount) FROM sales.store.orders"})
# サーバー側で有効にする:
MINILAKE_MCP=1 minilake --port 8000
カバレッジ
何がエミュレートされ、どの程度正直か。
以下の各行は、実際に実行されたか、または明確にラベル付けされています。範囲外のものは、本番コードが実行できない成功を偽装するのではなく、501 NOT_IMPLEMENTEDを返します。
| サービス | ステータス | その意味 |
|---|---|---|
| Unity Catalog | リアル | カタログ、スキーマ、テーブル、ボリューム、関数 — 各カタログは独自のDuckDBデータベースであり、ネイティブな3部構成のアドレス指定が可能です |
| UC権限 | 未実施CRUD | 実際の継承(カタログへの付与はスキーマとテーブルに有効)がありますが、権限は一切チェックされません |
| UC関数 | リアル | SQL関数は実際のDuckDBマクロになり、SELECT cat.sch.fn(x)が実際に計算されます — 登録エントリではありません |
| SQLステートメント | リアル | DuckDBで実行されます。すべての3つのフォーマットと両方のディスポジション、型付き結果マニフェスト付き |
| EXTERNAL Deltaテーブル | リアル | 正規のDeltaファイル。書き込みは生成されたSparkジョブを通じて行われ、読み取りはdelta_scan()を通じて行われます |
| ジョブ | リアル | 兄弟コンテナでのspark-submit(またはサブプロセスフォールバック)、実際のDAGスケジューリング、実際のログ、ワンショットruns/submit |
| SQLウェアハウス | リアル | 完全なCRUDとライフサイクル。ステートに関係なくステートメントが実行されます、ローカルで実行されるように |
| クエリ履歴 & 保存済みクエリ | リアル | サーバーバック、失敗も含む — 通常、履歴を開くのはそのためです |
| アラート | リアル | 条件は実際のクエリ結果に対して評価されるため、アラートはデータに対してトリガーされます — 保存された定数に対してではありません |
| Workspace, DBFS & Files | リアル | チャンクアップロードを備えたファイルベースのストレージ。生のバイト同期がbundle deployを機能させます |
| Secrets | リアル | 実際のCRUD。値はジョブ環境変数内でのみ解決可能で、APIを通じては決して解決されません |
| Web UI & notebooks | リアル | /uiのAthenaスタイルのSQLワークスペース、/jupyterにプロキシされたJupyterLab付き |
| MCPサーバー | リアル | MINILAKE_MCP=1でオプトイン:同じポートで67のツール、8つのリソース、4つのプロンプト |
| 永続化 | リアル | MINILAKE_PERSIST=1はシャットダウン時に状態をJSONとしてスナップショットし、起動時に復元します |
| クラスター | ステートマシン | CRUDと時間経過によるライフサイクル遷移 — 意図的にSparkコンピュートなし。それはジョブにあります |
| ポリシー & インスタンスプール | 未実施CRUD | それらは解決および検証されるため、それらを名前付けするバンドルはデプロイされます — しかし、ポリシーが制約するコンピュートはありません |
| 権限 | すべて許可CRUD | 実際の作成/読み取り/更新ですが、何も強制されません — これはシングルユーザーツールです |
| Workspace管理者 | 未実施CRUD | Git認証情報、IPアクセスリスト、初期化スクリプト、通知宛先、インスタンスプロファイル、ワークスペース設定 — terraform applyが通過する際に触れるもの |
| ID & SCIM | 未実施CRUD | ユーザー、グループ、サービスプリンシパル、SCIMフィルタリングとPATCH付き — レコードであり、認証情報ではありません。任意のトークンが依然として受け入れられます |
| トークン | 未実施CRUD | 値は一度だけ返され、実際のものと同じです — そして何も認証しません |
レガシーSQL (preview/sql) | リアル | 非推奨ルートでのクエリ、アラート、ダッシュボード — 最新ストアのアダプター。そのため、両方のサーフェスが1つのオブジェクトを参照します |
| DLT, Model Registry, Vector Search, Lakeview, Repos | 未実装 | 501 NOT_IMPLEMENTEDを返します — 大きな音で、あなたがそれを機能していると誤解しないように |
率直な話
MiniLakeではないもの。
これらは意図的な設計上の決定であり、バックログではありません。MiniLakeはローカルで実行する単一の開発者を対象としています — 共有のマルチテナントサーバーではありません。
認証なし
任意のトークンが受け入れられ、ユーザーは1人だけです。localhost以外に公開しないでください。
アクセス制御なし
Permissions APIは常にすべてを許可する実際のCRUDです — ここでのテストの合格は、実際のワークスペースでの権限については何も語りません。
Spark SQLではなくDuckDB
ステートメントはDuckDBの方言で実行されます。MCPサーバーはこの理由のために方言リソースを配布します。ドキュメントには変換テーブルがあります。
クラスター上のSparkなし
クラスターのライフサイクルはステートマシンです。実際のSparkはジョブを通じて、兄弟コンテナで実行されます。
シングルプロセス、HAなし
DuckDBはシングルライターなので、同時ロードはロックでシリアル化されます。開発やCIには十分ですが、デプロイメントターゲットではありません。
MANAGEDテーブルはSparkから見えない
これらはファイルのないDuckDBテーブルです。Sparkがデータを見る必要がある場合はEXTERNAL Deltaを使用してください — そのトレードオフがSQLを高速に保ちます。
エッジを明示することはポイントです:できないことを静かに偽装するエミュレーターは、エミュレーターがないよりも悪いです。
[画像]
あなたのレイクハウスを、localhostで、1つのコマンドで。
無料かつMITライセンス。アカウント不要、APIキー不要、クラウド請求なし — そして、終わったときにクラウドアカウントからアンインストールするものがありません。