8000 fix(docker): make the image work with no network at runtime by dmux · Pull Request #2 · dmux/minilake · GitHub
[go: up one dir, main page]

Skip to content

fix(docker): make the image work with no network at runtime - #2

Merged
dmux merged 2 commits into
mainfrom
fix/offline-docker-image
Aug 8, 2026
Merged

dmux merged 2 commits into
mainfrom
fix/offline-docker-image

Conversation

@dmux
@dmux dmux commented Aug 8, 2026
Copy link
Copy Markdown
Owner

Problem

docker run ghcr.io/dmux/minilake:latest downloaded two things on first use, so on a machine without internet the server booted and then failed on the first real query.

  1. DuckDB delta extension — duckdb_pool.py ran INSTALL delta at startup, fetching from extensions.duckdb.org into $HOME/.duckdb. Not a volume, so every fresh container re-downloaded it. The failure was swallowed as a warning and the health check stayed green, so it surfaced three layers away as a broken delta_scan(). FEATURES.md claimed this "fails loudly" — it did not.
  2. Spark Delta / Unity Catalog jars — spark-submit --packages resolved from Maven Central on the first job run. The Ivy cache on the data volume avoided repeat resolution but not the first fetch, and the volume starts empty.

Changes

DuckDB extension. Both Dockerfiles INSTALL it at build time into MINILAKE_DUCKDB_EXTENSION_DIR (/opt/duckdb-extensions), and the build fails outright if the fetch does not land — better than silently publishing an image that goes back to downloading at boot. At runtime the pool only LOADs it, with autoinstall_known_extensions=False so nothing can be fetched behind your back. A plain pip install minilake keeps the old INSTALL path; there is no image to bake anything into.

Spark jars. A new sparkjars build stage resolves Delta + the UC connector with spark-submit itself rather than curl — Ivy needs the ivy-*.xml metadata next to the jar, and without it re-resolves over the network even when the jar is on disk. The job container is a sibling and cannot see inside minilake's container, so _seed_ivy_cache() copies the baked cache onto the shared data volume once per volume, chmod'd for the Spark image's uid 185.

Both directories live outside WORKDIR: docker-compose.test.yml bind-mounts the repo over /opt/minilake and would otherwise hide them at runtime.

Still a network call: the Spark image docker pull. An image cannot contain another image. MINILAKE_SPARK_PREWARM=0 skips the attempt, and the docs say to pull it once up front.

Verification

  • Full Docker suite: 234 passed.
  • New tests/test_duckdb_extensions.py runs against the Docker stack (not skipped) and asserts the extension resolves to /opt/duckdb-extensions/v1.5.5/linux_amd64/delta.duckdb_extension — anywhere else means it was downloaded at runtime.
  • Four new _seed_ivy_cache tests: seeding, idempotency, non-clobbering, missing seed dir.
  • scripts/verify-offline.sh passes under docker run --network none.
  • Jars proven offline directly: spark-submit --packages on an --internal Docker network (no route out) reported 0 artifacts copied, 30 already retrieved and the script ran.

Version

1.5.1 → 1.6.0. Minor rather than patch: the image gains a capability it did not have, plus MINILAKE_IVY_SEED and MINILAKE_SPARK_PREWARM. No existing behaviour changes.

Review notes

  • The sparkjars stage is pinned to --platform=$BUILDPLATFORM (jars are architecture-independent, so it skips QEMU in the multi-arch release build). The DuckDB RUN is deliberately not — that extension is per-architecture and must run on the target platform.
  • Image size grows by roughly 100 MB.
  • Drive-by: docs/configuration.md documented MINILAKE_DUCKDB_MEMORY_LIMIT as "Passed to DuckDB", but it is never applied to any connection. Marked as a no-op; fixing it is out of scope here.

dmux added 2 commits August 8, 2026 13:18
`docker run ghcr.io/dmux/minilake` downloaded two things on first use, so an
offline machine got a server that booted and then failed on the first query.

The DuckDB `delta` extension was fetched from extensions.duckdb.org at startup,
into $HOME/.duckdb — not a volume, so every fresh container paid for it again.
The failure was swallowed as a warning and the health check stayed green, which
is why it surfaced three layers away, at delta_scan() time. Both Dockerfiles now
INSTALL it at build time into MINILAKE_DUCKDB_EXTENSION_DIR and the build fails
outright if the fetch does not land; at runtime the pool only LOADs it, with
autoinstall_known_extensions off so nothing can be fetched behind your back. A
plain `pip install minilake` keeps the INSTALL path, since there is no image to
bake anything into.

The Delta and Unity Catalog jars were resolved from Maven Central by
spark-submit --packages. A new build stage resolves them with spark-submit
itself rather than curl: Ivy needs the ivy-*.xml metadata alongside the jar, and
without it re-resolves over the network even when the jar is already on disk.
The job container is a sibling and cannot see inside this one, so the only place
both can reach is the data volume — _seed_ivy_cache copies the baked cache there
once per volume, chmod'd for the Spark image's uid 185.

The extension directory and the Ivy cache both live outside WORKDIR because
docker-compose.test.yml bind-mounts the repo over /opt/minilake, which would
otherwise hide them at runtime.

Verified with spark-submit on a --internal Docker network (no route out):
"0 artifacts copied, 30 already retrieved", and the script ran. scripts/verify-
offline.sh pins the whole thing under `docker run --network none`.

What an image cannot contain is another image, so the Spark image pull is still
a network call; MINILAKE_SPARK_PREWARM=0 skips the attempt and the docs say to
pull it once up front.
Minor rather than patch: the image gains a capability it did not have — it runs
with no network at all — and two new configuration knobs, MINILAKE_IVY_SEED and
MINILAKE_SPARK_PREWARM. Nothing existing changes behaviour.

release.yml refuses to publish when the tag and pyproject.toml disagree, so the
lock is regenerated in the same commit.
@dmux dmux self-assigned this Aug 8, 2026
@dmux dmux added the bug Something isn't working label Aug 8, 2026
@dmux
dmux merged commit 7820ab8 into main Aug 8, 2026
2 checks passed
@dmux
dmux deleted the fix/offline-docker-image branch September 30, 2026 01:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

0