Getting started with Lakekeeper
Spin up a full Lakekeeper stack locally with Docker Compose, then create your first namespace and Iceberg table through the REST catalog.
Runnable source: https://github.com/lakekeeper/lakekeeper/tree/main/examples/minimal.
Lakekeeper is an open-source Apache Iceberg™ REST catalog. In this tutorial you’ll run a complete lakehouse on your machine — catalog, metadata database, object storage, and three query engines — and write your first Iceberg table. It takes about ten minutes and everything runs in Docker.
Full source: the compose file and ready-made notebooks for this walkthrough live in the
minimalexample in the Lakekeeper repository.
What you’ll need
- Docker and Docker Compose (Docker Desktop includes both)
- Roughly 4 GB of free memory for the containers
No cloud account is required. The stack uses Postgres for catalog metadata and SeaweedFS (an S3-compatible store) for data, so it behaves exactly like a cloud deployment without touching a cloud provider.
1. Start the stack
git clone https://github.com/lakekeeper/lakekeeper.git
cd lakekeeper/examples/minimal
docker compose up
This brings up Lakekeeper, Postgres, SeaweedFS, and a Jupyter environment preloaded with Spark, PyIceberg, plus Trino and StarRocks — three engines all pointed at the same catalog. Crucially, SeaweedFS runs with its IAM/STS service enabled, so Lakekeeper can vend short-lived credentials to those engines rather than handing out long-lived keys.
Once it’s healthy, you have three things open to you:
- Lakekeeper UI — http://localhost:8181
- Jupyter notebooks — http://localhost:8888
- Swagger / REST API — http://localhost:8181/swagger-ui/#/
2. Bootstrap and create a warehouse
Open Jupyter at http://localhost:8888 and run the provided bootstrap notebook. Bootstrapping initializes the metadata store and creates the first project; the notebook then creates a warehouse — the top-level container that maps a logical catalog to a physical storage location (the SeaweedFS bucket here).
You can watch the warehouse, namespaces, and tables appear live in the Lakekeeper UI as the notebook runs.
3. Connect an engine and write a table
Any Iceberg REST client can now connect at http://localhost:8181/catalog. From Spark, the catalog is configured like this — note the last line, which asks Lakekeeper to vend temporary credentials so Spark never holds a storage key:
spark.conf.set("spark.sql.catalog.lakekeeper", "org.apache.iceberg.spark.SparkCatalog")
spark.conf.set("spark.sql.catalog.lakekeeper.type", "rest")
spark.conf.set("spark.sql.catalog.lakekeeper.uri", "http://lakekeeper:8181/catalog")
spark.conf.set("spark.sql.catalog.lakekeeper.warehouse", "demo")
spark.conf.set("spark.sql.catalog.lakekeeper.header.X-Iceberg-Access-Delegation", "vended-credentials")
Then create a namespace and a table and write a few rows:
CREATE NAMESPACE IF NOT EXISTS lakekeeper.sales;
CREATE TABLE lakekeeper.sales.orders (
id BIGINT,
region STRING,
amount DECIMAL(10, 2)
) USING iceberg;
INSERT INTO lakekeeper.sales.orders VALUES
(1, 'EMEA', 42.00),
(2, 'AMER', 17.50);
SELECT region, sum(amount) FROM lakekeeper.sales.orders GROUP BY region;
That’s a real Iceberg table — snapshots, schema, and manifests — governed by Lakekeeper and stored in SeaweedFS. Now open the Trino or StarRocks notebook and query the same table through the same catalog: one governed source of truth, many engines.
4. Tear it down
docker compose down -v
The -v flag removes the volumes too, so you start clean next time.
Where to go next
- Centralized access & vended credentials — how those short-lived credentials work, and why routing every engine through one catalog is the whole point.
- Access control with Lakekeeper — add an identity provider and control who can touch which warehouse.
- Swap SeaweedFS for real S3, GCS, or Azure — only the warehouse’s storage profile changes.
For the full configuration reference, see the Lakekeeper docs.