docker2vm converts OCI container images (or Dockerfiles via BuildKit) into VM-compatible outputs. Today, the runtime materialization target is Gondolin.
It follows an OCI-first flow inspired by "Docker without Docker":
- resolve/pull an OCI image
- apply layers to a root filesystem
- inject Gondolin runtime glue (init/sandbox binaries/modules)
- materialize
rootfs.ext4(and optionally full guest assets) - run with Gondolin
Docker containers share the host kernel. Gondolin runs workloads inside a VM, so we need to convert container artifacts into a bootable guest rootfs while keeping Gondolin's kernel/init/runtime contract.
- pinned Gondolin runtime dependency (
@earendil-works/gondolin@0.2.1) for guest-asset retrieval oci2gondolincore converter- input:
--image,--oci-layout,--oci-tar(exactly one) - platform:
linux/amd64,linux/arm64 - modes:
rootfs,assets - dry-run planning
- input:
dockerfile2gondolinthin wrapper- builds Dockerfile to OCI tar (BuildKit) and delegates to
oci2gondolin
- builds Dockerfile to OCI tar (BuildKit) and delegates to
- secure-ish layer handling
- digest verification
- path traversal checks
- symlink-parent protections
- OCI whiteout handling
- Gondolin runtime integration
- base rootfs extraction
- runtime file/module injection
- compatibility symlinks
- CI + E2E smoke test (GitHub Actions)
- Bun >= 1.2 — https://bun.com/
e2fsprogs(mke2fs,debugfs) — https://e2fsprogs.sourceforge.net/- QEMU (for runtime smoke checks) — https://www.qemu.org/download/
- Docker (only required for
dockerfile2gondolin) — https://docs.docker.com/get-docker/
docker2vm uses @earendil-works/gondolin@0.2.1 as a runtime dependency and resolves/downloads guest assets automatically during conversion.
If you also want to run generated assets with gondolin exec, install the Gondolin CLI:
- CLI docs: https://earendil-works.github.io/gondolin/cli/
- Package: https://www.npmjs.com/package/@earendil-works/gondolin
On macOS,
docker2vmchecks common Homebrewe2fsprogslocations automatically; updatingPATHis usually optional.
bun test
bun run typecheck
bun run buildbun run test:integrationThe CI integration matrix currently validates:
alpine:3.20debian:bookworm-slimubuntu:24.04fedora:41archlinux:latest
For each distro row, tests run a distro-specific probe command (for example /etc/debian_version, /etc/fedora-release, etc.), assert that probe does not match on the base Gondolin guest image, and verify /bin/busybox executes inside the converted image.
--platform selects which OCI image variant to convert, and should match the architecture you plan to run in Gondolin. This applies to both oci2gondolin and dockerfile2gondolin.
- Apple Silicon / arm64 Linux hosts:
linux/arm64 - Intel / amd64 hosts:
linux/amd64 - If omitted, both commands default from host arch (
x64 -> linux/amd64,arm64 -> linux/arm64). - You can always override manually with
--platform linux/amd64or--platform linux/arm64.
For helper scripts:
e2e:smokeusesPLATFORM- integration tests use
INTEGRATION_PLATFORM
Cross-arch builds are possible at image-selection time, but for reliable runtime execution you should use a platform that matches the runtime guest architecture.
bun run oci2gondolin -- \
--image busybox:latest \
--platform linux/arm64 \
--mode assets \
--out ./out/busybox-assetsGONDOLIN_GUEST_DIR=./out/busybox-assets gondolin exec -- /bin/busybox echo helloCreate a Dockerfile and convert it through BuildKit:
cat > /tmp/Dockerfile.demo <<'EOF'
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y --no-install-recommends cowsay && rm -rf /var/lib/apt/lists/*
CMD ["/bin/sh"]
EOF
bun run dockerfile2gondolin -- \
--file /tmp/Dockerfile.demo \
--context /tmp \
--platform linux/arm64 \
--mode assets \
--out ./out/demo-assetsThen run:
GONDOLIN_GUEST_DIR=./out/demo-assets gondolin exec -- /usr/games/cowsay "hello"Local/CI smoke test script:
bun run e2e:smokeOptional env overrides:
PLATFORM(default auto-detected from host arch)IMAGE(defaultbusybox:latest)OUT_DIR(default./out/e2e-busybox-assets)
Example:
PLATFORM=linux/amd64 IMAGE=busybox:latest bun run e2e:smokeoci2gondolin (--image REF | --oci-layout PATH | --oci-tar PATH) [options]
--platform linux/amd64|linux/arm64
--mode rootfs|assets
--out PATH
--dry-run
dockerfile2gondolin --file PATH --context PATH --out PATH [options]
--platform linux/amd64|linux/arm64
--mode rootfs|assets
--builder docker-buildx|buildctl
--target NAME
--build-arg KEY=VALUE (repeatable)
--secret SPEC (repeatable)
--dry-run
- Resolver: pick correct manifest for requested platform
- Puller: fetch blobs + verify digest
- Layer apply: unpack tar layers in order with whiteouts
- Materialize:
- emit
rootfs.ext4 - emit
meta.json - in
assetsmode also copy kernel/initramfs and writemanifest.json
- emit
- This repo is standalone; Gondolin core is not modified.
- Gondolin upstream repository: https://github.com/earendil-works/gondolin
out/is generated output and ignored by git.