Skip to content

feat(cli): forkd from-image — Docker image → snapshot in one command#136

Merged
WaylandYang merged 1 commit into
mainfrom
feat/cli-pull-oci
May 21, 2026
Merged

feat(cli): forkd from-image — Docker image → snapshot in one command#136
WaylandYang merged 1 commit into
mainfrom
feat/cli-pull-oci

Conversation

@WaylandYang
Copy link
Copy Markdown
Contributor

Summary

Closes the OCI-native distribution gap. Before this PR, going from a Docker image to a forkd snapshot required two commands:
```bash
forkd parent build python:3.12-slim --output python.ext4 --extra python3-numpy
forkd snapshot --tag py-numpy --kernel ./vmlinux-6.1.141 --rootfs python.ext4 --tap forkd-tap0
```

After this PR, one command:
```bash
forkd from-image python:3.12-slim --tag py-numpy --extra python3-numpy
```

Same pipeline (Docker pull → ext4 → boot + warmup → pause → register tag), wrapped in one verb. boxlite's positioning is "docker pull X and you're done"; this matches that surface.

Design

  • New `Cmd::FromImage` subcommand, dispatch in `main()`.
  • New `from_image_cmd()` calls existing `parent_build_cmd` + `snapshot_cmd` internally — no new boot/snapshot machinery, just convenience chaining.
  • Kernel resolution: `--kernel` arg > `FORKD_KERNEL` env > standard search paths (`./vmlinux-6.1.141`, `./vmlinux`, `/var/lib/forkd/kernels/vmlinux`, `/usr/local/share/forkd/vmlinux`). Defaults so most users won't need to pass `--kernel`.
  • Rootfs cached at `/var/cache/forkd/.ext4` (same convention as `forkd run`); re-running with the same image skips the Docker step.
  • All forkd-vmm boot/snapshot tuning knobs surfaced as flags (`--size-mib`, `--boot-wait-secs`, `--mem-size-mib`, `--tap`).

Smoke tests on dev box

```
$ forkd from-image --help
Build a forkd snapshot from a Docker image in one command.
...

$ forkd from-image alpine:latest --tag t --kernel /nonexistent
Error: kernel not found: /nonexistent

$ forkd from-image alpine:latest --tag t # no kernel in cwd or env
Error: no kernel found; pass --kernel or set FORKD_KERNEL. searched: ./vmlinux-6.1.141, ./vmlinux, /var/lib/forkd/kernels/vmlinux, /usr/local/share/forkd/vmlinux
```

End-to-end pipeline not run in CI (requires root + Docker + ~3 minutes per image); the underlying `parent_build_cmd` and `snapshot_cmd` are already exercised separately. This PR is convenience wiring.

Files

  • `crates/forkd-cli/src/main.rs` — new `Cmd::FromImage` variant (~40 lines), dispatch (~12 lines), `from_image_cmd` + `find_default_kernel` (~95 lines). 147 total insertions, no deletions.

🤖 Generated with Claude Code

Closes the OCI-native distribution gap. boxlite's pitch is
\"docker pull python:slim and you're done\"; forkd previously
required users to chain \`forkd parent build\` (image → ext4) and
\`forkd snapshot --kernel ... --rootfs ...\` themselves. This wraps
the pipeline into one verb.

  forkd from-image python:3.12-slim --tag py-numpy --extra python3-numpy
  # → builds rootfs (cached), boots parent, warms up, snapshots,
  # registers 'py-numpy' tag. Ready to fork.

Resolves \`--kernel\` by searching standard paths if unset:
  ./vmlinux-6.1.141 → ./vmlinux → /var/lib/forkd/kernels/vmlinux →
  /usr/local/share/forkd/vmlinux

Calls existing parent_build_cmd and snapshot_cmd internally — no
new boot/snapshot machinery, just the convenience chain that
boxlite-style users expect.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@WaylandYang WaylandYang merged commit bba45fa into main May 21, 2026
2 checks passed
@WaylandYang WaylandYang deleted the feat/cli-pull-oci branch May 21, 2026 05:51
WaylandYang added a commit that referenced this pull request May 21, 2026
…start (#137)

The 3 CLI commands shipped 2026-05-21 (#134, #135, #136) collapse the
new-user setup from 4 hand-pasted commands to a single \`forkd doctor\`
+ \`forkd from-image\` flow. Surface this prominently in Quick start so
visitors landing from a Twitter / blog link see the modern story.

- README.md: new \"Confirm your host is ready\" subsection leads with
  \`forkd doctor\`. New \"From a Docker image (one command)\" subsection
  shows \`forkd from-image python:3.12-slim --tag py-numpy\`. New
  \"Probe your install's latency\" subsection shows \`forkd bench\` with
  example output.
- README-zh.md: parallel sections in Chinese.

The original Hub-pull, from-source, and multi-child-fork-out sections
are unchanged — those audiences still need them. New subsections come
first since they're the most-likely user path.

No code changes.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
WaylandYang added a commit that referenced this pull request May 21, 2026
* docs: feature \`forkd doctor\` / \`from-image\` / \`bench\` in Quick start

The 3 CLI commands shipped 2026-05-21 (#134, #135, #136) collapse the
new-user setup from 4 hand-pasted commands to a single \`forkd doctor\`
+ \`forkd from-image\` flow. Surface this prominently in Quick start so
visitors landing from a Twitter / blog link see the modern story.

- README.md: new \"Confirm your host is ready\" subsection leads with
  \`forkd doctor\`. New \"From a Docker image (one command)\" subsection
  shows \`forkd from-image python:3.12-slim --tag py-numpy\`. New
  \"Probe your install's latency\" subsection shows \`forkd bench\` with
  example output.
- README-zh.md: parallel sections in Chinese.

The original Hub-pull, from-source, and multi-child-fork-out sections
are unchanged — those audiences still need them. New subsections come
first since they're the most-likely user path.

No code changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(cli): \`forkd ls\` + \`forkd kill\` — direct sandbox lifecycle

Two small subcommands that wrap GET /v1/sandboxes and DELETE
/v1/sandboxes/:id so users don't have to hand-write curl. Same
ergonomics as \`docker ps\` / \`docker rm\`.

  forkd ls
    ID                    SNAPSHOT                       PID       NETNS           GUEST_ADDR
    sb-6a0e8d4f-0023      coding-agent-fork-prewarm-v1   123456    forkd-child-1   10.42.0.2:8888
    sb-6a0e8d50-0024      speculative-1234               123457    forkd-child-2   10.42.0.2:8888
    ...
    2 sandboxes

  forkd kill sb-6a0e8d4f-0023
    ✓ sb-6a0e8d4f-0023

  forkd kill --all
  forkd kill --tag speculative-1234

Implementation in crates/forkd-cli/src/sandbox.rs (~170 LOC), wired
in main.rs as Cmd::Ls / Cmd::Kill. Reads FORKD_URL / FORKD_TOKEN
from env like the other daemon-talking commands.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant