|
1 | | -# Gondolin Image Tooling Plan |
| 1 | +# Gondolin Image Tools |
2 | 2 |
|
3 | | -## Goal |
4 | | -Create external tooling that converts container artifacts into images Gondolin can boot **without modifying Gondolin core code**. |
| 3 | +External OCI-first tooling that converts container artifacts into Gondolin-bootable images **without modifying Gondolin core**. |
5 | 4 |
|
6 | | -## Recommendation |
7 | | -Build in this order: |
| 5 | +## Status |
8 | 6 |
|
9 | | -1. **`oci2gondolin` first** (core converter) |
10 | | -2. **`dockerfile2gondolin` second** (thin wrapper around BuildKit + `oci2gondolin`) |
| 7 | +Implemented and working: |
11 | 8 |
|
12 | | -This keeps complexity low and allows multiple input paths (registry, CI-produced OCI tar, local OCI layout). |
| 9 | +- ✅ `oci2gondolin` core converter |
| 10 | + - input sources: `--image`, `--oci-layout`, `--oci-tar` (exactly one) |
| 11 | + - platform selection (`linux/amd64`, `linux/arm64`, plus short forms) |
| 12 | + - output modes: `rootfs`, `assets` |
| 13 | + - structured dry-run plans |
| 14 | + - actionable validation + runtime errors |
| 15 | +- ✅ OCI resolver/puller for public registries (Bearer token flow) |
| 16 | +- ✅ digest verification + local blob cache |
| 17 | +- ✅ layer apply engine (tar+gzip, whiteouts, secure extraction checks) |
| 18 | +- ✅ materialization |
| 19 | + - ext4 image creation (`rootfs.ext4`) |
| 20 | + - metadata emission (`meta.json`) |
| 21 | + - assets output (`vmlinuz-virt`, `initramfs.cpio.lz4`, `rootfs.ext4`, `manifest.json`) |
| 22 | +- ✅ `dockerfile2gondolin` thin wrapper |
| 23 | + - BuildKit via `docker buildx` (temp docker-container builder) |
| 24 | + - BuildKit via `buildctl` |
| 25 | + - delegates conversion to `oci2gondolin` |
| 26 | +- ✅ unit tests for argument parsing/validation |
13 | 27 |
|
14 | | -## Why OCI-first |
15 | | -- Dockerfile support is effectively a full build system |
16 | | -- OCI image/manifest/layers are a stable output contract |
17 | | -- Reusable converter for any upstream build stack |
| 28 | +## Requirements |
18 | 29 |
|
19 | | -## Deliverables |
20 | | -- `oci2gondolin` CLI |
21 | | -- `dockerfile2gondolin` CLI (wrapper) |
22 | | -- Test fixtures + conformance tests |
23 | | -- Basic docs and examples |
| 30 | +- Bun 1.2+ |
| 31 | +- Docker (for `dockerfile2gondolin`) |
| 32 | +- `e2fsprogs` (`mke2fs`, `debugfs`) for rootfs creation/injection |
| 33 | +- (optional runtime verification) `@earendil-works/gondolin` CLI + QEMU |
| 34 | + |
| 35 | +macOS helpers: |
| 36 | + |
| 37 | +```bash |
| 38 | +brew install e2fsprogs qemu |
| 39 | +``` |
| 40 | + |
| 41 | +## Install |
| 42 | + |
| 43 | +```bash |
| 44 | +bun install |
| 45 | +``` |
| 46 | + |
| 47 | +## Quickstart |
| 48 | + |
| 49 | +### 1) Validate build + tests |
| 50 | + |
| 51 | +```bash |
| 52 | +bun test |
| 53 | +bun run typecheck |
| 54 | +bun run build |
| 55 | +``` |
| 56 | + |
| 57 | +### 2) Convert BusyBox image to Gondolin assets |
| 58 | + |
| 59 | +```bash |
| 60 | +bun run oci2gondolin -- \ |
| 61 | + --image busybox:latest \ |
| 62 | + --platform linux/arm64 \ |
| 63 | + --mode assets \ |
| 64 | + --out ./out/busybox-assets |
| 65 | +``` |
| 66 | + |
| 67 | +### 3) Run with Gondolin package |
| 68 | + |
| 69 | +```bash |
| 70 | +GONDOLIN_GUEST_DIR=./out/busybox-assets bunx gondolin exec -- /bin/busybox echo hello |
| 71 | +``` |
| 72 | + |
| 73 | +### 4) Dockerfile -> Gondolin (wrapper) |
| 74 | + |
| 75 | +```bash |
| 76 | +bun run dockerfile2gondolin -- \ |
| 77 | + --file ./Dockerfile.busybox \ |
| 78 | + --context . \ |
| 79 | + --platform linux/arm64 \ |
| 80 | + --mode assets \ |
| 81 | + --out ./out/busybox-from-dockerfile |
| 82 | +``` |
| 83 | + |
| 84 | +Then: |
| 85 | + |
| 86 | +```bash |
| 87 | +GONDOLIN_GUEST_DIR=./out/busybox-from-dockerfile bunx gondolin exec -- /bin/busybox echo wrapper-ok |
| 88 | +``` |
| 89 | + |
| 90 | +## Distro smoke matrix (arm64) |
| 91 | + |
| 92 | +Validated with `gondolin exec`: |
| 93 | + |
| 94 | +- Alpine (`alpine:3.20`) |
| 95 | +- Debian (`debian:bookworm-slim`) |
| 96 | +- Ubuntu (`ubuntu:24.04`) |
| 97 | +- Fedora (`fedora:latest`) |
| 98 | +- Arch Linux ARM (`menci/archlinuxarm:latest`) |
| 99 | + |
| 100 | +### macOS note (case-sensitive temp workspace) |
| 101 | + |
| 102 | +Some images (notably Arch/Fedora) include case-sensitive filesystem paths that conflict on default case-insensitive macOS volumes. Use a case-sensitive temp mount and point `TMPDIR` at it when converting: |
| 103 | + |
| 104 | +```bash |
| 105 | +CASE_ROOT=$(mktemp -d) |
| 106 | +IMG="$CASE_ROOT/oci2gondolin-casefs.sparseimage" |
| 107 | +MP="$CASE_ROOT/mount" |
| 108 | +mkdir -p "$MP" |
| 109 | + |
| 110 | +hdiutil create -size 8g -type SPARSE -fs 'Case-sensitive APFS' -volname Oci2GondolinCase "$IMG" |
| 111 | +hdiutil attach "$IMG" -mountpoint "$MP" -nobrowse |
| 112 | + |
| 113 | +TMPDIR="$MP" bun run oci2gondolin -- --image menci/archlinuxarm:latest --platform linux/arm64 --mode assets --out ./out/arch-assets |
| 114 | +GONDOLIN_GUEST_DIR=./out/arch-assets bunx gondolin exec -- /bin/sh -lc 'cat /etc/os-release | head -n 2' |
| 115 | + |
| 116 | +hdiutil detach "$MP" |
| 117 | +rm -rf "$CASE_ROOT" |
| 118 | +``` |
| 119 | + |
| 120 | +## Dry-run examples |
| 121 | + |
| 122 | +```bash |
| 123 | +bun run oci2gondolin -- --image busybox:latest --out ./out/plan --dry-run |
| 124 | +bun run dockerfile2gondolin -- --file ./Dockerfile --context . --out ./out/plan --dry-run |
| 125 | +``` |
| 126 | + |
| 127 | +## Commands |
| 128 | + |
| 129 | +### `oci2gondolin` |
| 130 | + |
| 131 | +- Input source (exactly one): |
| 132 | + - `--image <ref>` |
| 133 | + - `--oci-layout <path>` |
| 134 | + - `--oci-tar <path>` |
| 135 | +- `--platform linux/amd64|linux/arm64` (or `amd64|arm64`) |
| 136 | +- `--mode rootfs|assets` (default: `rootfs`) |
| 137 | +- `--out <path>` (required) |
| 138 | +- `--dry-run` |
| 139 | + |
| 140 | +### `dockerfile2gondolin` |
| 141 | + |
| 142 | +- `--file <path>` (required) |
| 143 | +- `--context <path>` (required) |
| 144 | +- `--out <path>` (required) |
| 145 | +- `--platform linux/amd64|linux/arm64` |
| 146 | +- `--mode rootfs|assets` |
| 147 | +- `--builder docker-buildx|buildctl` |
| 148 | +- `--target <stage>` |
| 149 | +- `--build-arg KEY=VALUE` (repeatable) |
| 150 | +- `--secret ...` (repeatable) |
| 151 | +- `--dry-run` |
| 152 | + |
| 153 | +## Architecture |
| 154 | + |
| 155 | +- `oci2gondolin` contains the converter pipeline (resolver/puller/layer-apply/materialize) |
| 156 | +- converter applies OCI layers on top of an extracted Gondolin base rootfs to preserve runtime compatibility (`sandboxd`, `sandboxfs`, init flow) |
| 157 | +- `dockerfile2gondolin` is a wrapper layer around BuildKit + `oci2gondolin` |
| 158 | +- gondolin core remains external/unmodified |
| 159 | + |
| 160 | +## Planning docs |
24 | 161 |
|
25 | | -## Directory contents |
26 | 162 | - [`01-oci2gondolin-spec.md`](./01-oci2gondolin-spec.md) |
27 | 163 | - [`02-dockerfile2gondolin-wrapper.md`](./02-dockerfile2gondolin-wrapper.md) |
28 | 164 | - [`03-implementation-phases.md`](./03-implementation-phases.md) |
|
0 commit comments