Skip to content

Latest commit

 

History

History
202 lines (146 loc) · 5.72 KB

File metadata and controls

202 lines (146 loc) · 5.72 KB

docker2vm

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

Why this exists

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.

Current features

  • pinned Gondolin runtime dependency (@earendil-works/gondolin@0.2.1) for guest-asset retrieval
  • oci2gondolin core converter
    • input: --image, --oci-layout, --oci-tar (exactly one)
    • platform: linux/amd64, linux/arm64
    • modes: rootfs, assets
    • dry-run planning
  • dockerfile2gondolin thin wrapper
    • builds Dockerfile to OCI tar (BuildKit) and delegates to oci2gondolin
  • 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)

Requirements

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:

On macOS, docker2vm checks common Homebrew e2fsprogs locations automatically; updating PATH is usually optional.

Platform setup guides

Quickstart

1) Validate

bun test
bun run typecheck
bun run build

1b) Run integration tests

bun run test:integration

The CI integration matrix currently validates:

  • alpine:3.20
  • debian:bookworm-slim
  • ubuntu:24.04
  • fedora:41
  • archlinux: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.

Choosing the build platform (--platform)

--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/amd64 or --platform linux/arm64.

For helper scripts:

  • e2e:smoke uses PLATFORM
  • 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.

2) Convert image -> assets

bun run oci2gondolin -- \
  --image busybox:latest \
  --platform linux/arm64 \
  --mode assets \
  --out ./out/busybox-assets

3) Run with Gondolin

GONDOLIN_GUEST_DIR=./out/busybox-assets gondolin exec -- /bin/busybox echo hello

Dockerfile flow

Create 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-assets

Then run:

GONDOLIN_GUEST_DIR=./out/demo-assets gondolin exec -- /usr/games/cowsay "hello"

End-to-end smoke test

Local/CI smoke test script:

bun run e2e:smoke

Optional env overrides:

  • PLATFORM (default auto-detected from host arch)
  • IMAGE (default busybox:latest)
  • OUT_DIR (default ./out/e2e-busybox-assets)

Example:

PLATFORM=linux/amd64 IMAGE=busybox:latest bun run e2e:smoke

CLI summary

oci2gondolin

oci2gondolin (--image REF | --oci-layout PATH | --oci-tar PATH) [options]

--platform linux/amd64|linux/arm64
--mode rootfs|assets
--out PATH
--dry-run

dockerfile2gondolin

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

Architecture overview

  1. Resolver: pick correct manifest for requested platform
  2. Puller: fetch blobs + verify digest
  3. Layer apply: unpack tar layers in order with whiteouts
  4. Materialize:
    • emit rootfs.ext4
    • emit meta.json
    • in assets mode also copy kernel/initramfs and write manifest.json

Repo notes