Kern runs containers from a 1.52 MB binary with no daemon

Kern runs containers from a 1.52 MB binary with no daemon

Kern is a command-line container and resource runtime released as a single static binary: 1.52 MB in the size-optimized release build, or 1.91 MB from a plain cargo install from source. It ships as one file with no daemon, no socket and nothing to start in the background, and its headline claim is that it produces a real, kernel-enforced container in about 3.5 milliseconds. The project describes itself as one binary that manages resources, isolation being the first of them, rather than a single row on a features comparison table: a container runtime, a sandbox, a resource slicer and a stack runner combined.

As a container engine, kern works with real OCI images: it can pull one, build one from a Dockerfile, then commit, push, save or load it, and a box built from an image starts in about 3.5 ms. Every box is rootless by default, where Docker's rootless mode is opt-in: kern isolates user, PID, mount, network, UTS and IPC namespaces, pivots in an overlay or read-only root, applies a deny-by-default seccomp allowlist and enforces cgroup v2 limits. One flag, --security-profile untrusted, turns on that entire hardened bundle at once, the seccomp allowlist, dropping all capabilities, and a read-only filesystem, and a separate --require-limits flag refuses to start a box unless its memory and process caps are actually being enforced.

Resource limits are handled through named profiles declared once in a kern.toml file and attached by name, whether to a sandboxed box or to a bare process on the host through kern run, both drawing on the same caps. There are three kinds: vcpu: for CPU cores and memory, vdisk: for a size-capped scratch disk, and vgpio: for device nodes. A vdisk: profile becomes a RAM-backed tmpfs when kern runs rootless and an ext4-on-loop image with a real, enforced quota when it runs privileged, and kern reports which one a given profile actually got rather than leaving the user to assume. A vgpio: profile is chip-granular, not per-line: naming a device node grants exactly that node, but requesting a specific pin, for example pins = [17], still binds the whole /dev/gpiochipN character device, because the kernel has no per-line mount boundary; the pin list is cooperative metadata, not an enforced boundary.

Kern also runs multi-container stacks through kern compose, which reads either kern's own kern-compose.toml format or an existing docker-compose.yml with no conversion step, mapping one stack to one pod with services reaching each other by name. In the project's own example, a two-service stack, a Postgres database and an Adminer web front end, starts both official images, lets the web service reach the database by name, and publishes the port to the host; once the images are cached, the web tier begins serving in about 0.3 seconds, and the whole running stack uses about 66 MB of memory with no daemon running underneath it. The project positions this as a local development loop rather than a production orchestrator: it does not support Swarm-style clustering or overlay networks.

Around the runtime, kern ships operational commands, including ps, logs, exec, stats, inspect, wait, a live top TUI, and a doctor command that checks whether boxes can run on the current machine, and every read command can also return JSON instead of a table, so output is scriptable. For running untrusted or AI-generated code specifically, the project ships kern-sandbox, a dependency-free Python and Node binding that runs each call in a fresh, isolated box by default, network off, with memory and process-count caps, dropped capabilities, bounded output and an enforced timeout; a Sandbox object can keep a workspace alive across calls, and a warm_kernel() mode keeps one interpreter running for sub-millisecond cells at the cost of weaker isolation. Faults such as a timeout, an OOM kill or a blocked system call come back as a field on the result rather than as a raised exception. Kern also ships an MCP server, kern-mcp, that gives MCP clients such as Claude Desktop or Cursor a local, sandboxed code interpreter through four tools, run_code, write_file, read_file and list_files, with each call running in a fresh, network-off box while files persist across calls in an on-disk workspace.

The project is explicit about what kern is not. It is not a hypervisor: its isolation boundary is the Linux kernel itself, so a kernel privilege-escalation bug is a full escape, a condition it says Docker and Podman share too, which it gives as the reason tools such as gVisor and Firecracker exist. Its own SECURITY.md states, ahead of any other claim, that this isolation rests on an unprivileged user namespace, which the project itself calls a fertile source of kernel LPE bugs. It is not a boundary around whatever a user chooses to mount in: passing -v $HOME:/host hands a box the user's home directory, and options such as --net host or --privileged are named opt-outs rather than incidents kern prevents; the one path it does refuse to let a user bind is its own runtime registry. It is not a Docker Engine reimplementation, since it reads Docker's file formats but not its API, with no overlay networks, plugins or Swarm support, and it is not a Kubernetes runtime, since it implements no CRI and points Kubernetes users to containerd or CRI-O instead. GPU resource slices are not shipped yet either; the project calls them a roadmap item with no code in this release, so, in its own words, there is nothing here yet to trust or to attack.

Kern needs a Linux kernel with unprivileged user namespaces and cgroup v2. It runs on Linux, on WSL2 using a pre-baked root filesystem it ships, and on ARM boards including Raspberry Pi, Jetson and Arduino UNO Q, but there is no native Windows build. The fastest install path is a shell script that downloads the correct static binary for x86_64 or aarch64, verifies its SHA256 checksum, and refuses to install a download that fails that check; building from source instead pulls in exactly one crate, libc, since kern parses JSON and OCI manifests by hand and shells out to the curl and tar already on the machine rather than linking its own TLS stack, and a full clone, build and install took 36 seconds on the project's own benchmark desktop, an Intel i7-14700KF, running longer on a small ARM board. On that same desktop, under Linux 7.0.0 with the release binary, the project's benchmark script starts 3,000 boxes at once in about 2.2 seconds, with each running box then costing roughly 0.3 MB of memory, though it notes these figures will vary with the reader's own CPU, kernel and filesystem.

Key facts

  • Kern's release binary is 1.52 MB (1.91 MB when built from source with a plain cargo install); it runs with no daemon or background process and uses 0 RAM at rest.
  • A box built from an OCI image starts in about 3.5 milliseconds, and every box is rootless by default, isolating user, PID, mount, network, UTS and IPC namespaces behind a deny-by-default seccomp allowlist and cgroup v2 limits.
  • Kern compose reads an existing docker-compose.yml with no conversion step; in the project's own two-service example (Postgres plus Adminer), the web tier serves within about 0.3 seconds once images are cached and the stack runs on roughly 66 MB of memory.
  • CPU, memory, disk and GPIO limits are declared once as named profiles in kern.toml and can be attached either to a sandboxed box or to a bare host process through kern run, applying the same caps either way.
  • The kern-sandbox Python and Node bindings and the kern-mcp server give coding agents, including Claude Desktop and Cursor via MCP, a local sandboxed interpreter that runs each call network-off with capped memory, dropped capabilities and an enforced timeout, returning faults like timeouts or OOM kills as data rather than exceptions.

Why it matters

Kern's own comparison point is direct: it says Docker Desktop starts a background VM before a user's first container even runs, while kern is a single static binary that uses no RAM until a box actually runs, and starts one from an OCI image in about 3.5 milliseconds. It bundles what several separate tools usually cover: a container engine that speaks real OCI images, a rootless sandbox, a named resource-limiting layer (vcpu:, vdisk:, vgpio:) that applies the same caps to a sandboxed box or to a bare host process, and a stack runner that reads an unmodified docker-compose.yml. Its second stated purpose is running untrusted and AI-generated code specifically: it ships Python and Node bindings plus an MCP server built to hand coding agents a disposable, capped execution environment, positioning kern for exactly the kind of agent tool calls, CI jobs and build steps that need somewhere cheap and contained to run code nobody has reviewed.

Who it affects

Kern targets developers who need to run code they did not personally vet: agent tool calls, CI jobs, build steps and notebook-style code cells, and the project says so directly, describing itself as being for code the user already chose to run and whose blast radius the user owns, not for hostile code from strangers or for multi-tenant hosting on a kernel shared with other tenants. Its ARM support (Raspberry Pi, Jetson, Arduino UNO Q) together with the vgpio: device-node profile extends that to developers building on embedded or IoT-style boards who need to hand a sandboxed process one specific piece of hardware. Teams already standardized on docker-compose.yml files gain a no-daemon way to run those same stacks locally. Through the kern-sandbox bindings and the kern-mcp server, builders of coding agents and users of MCP clients such as Claude Desktop or Cursor gain a ready-made local code interpreter rather than having to build sandboxing themselves. It is explicitly not aimed at anyone needing a Kubernetes runtime, since it implements no CRI, or at GPU-isolated workloads, since no GPU code ships in this release.

How to use it

The fastest path is the installer script (curl -fsSL https://raw.githubusercontent.com/getkern/kern/main/install.sh | sh), which detects x86_64 or aarch64, installs to ~/.local/bin, or /usr/local/bin as root, or a custom KERN_INSTALL_DIR, and verifies the download's SHA256 checksum before installing it; the two commands for checking that checksum by hand are documented too, for anyone who prefers not to pipe a script into a shell. Building from source needs only Rust and one command, cargo install --git https://github.com/getkern/kern getkern --locked, and the project reports that a full clone, build and install took 36 seconds on an Intel i7-14700KF desktop, longer on a small ARM board. Kern needs a Linux kernel with unprivileged user namespaces and cgroup v2, and runs on Linux, on WSL2 with a pre-baked root filesystem it ships, and on ARM boards; there is no native Windows build. Typical commands include kern box dev --image alpine -it -- sh for a throwaway shell in an OCI image, kern run --memory 256M --cpus 0.5 -- ./crunch to cap a bare process with no sandbox at all, kern box svc with --restart and --health-cmd flags to run a restarted, health-checked service, and kern compose stack.toml up to bring up a multi-box stack from either kern's own format or a docker-compose.yml. Running untrusted code adds one flag, --security-profile untrusted, bundling the seccomp allowlist, dropped capabilities and a read-only filesystem in one step, and --require-limits then refuses to start a box unless its memory and process caps are actually being enforced. The project ships 90 runnable examples plus reference docs, including docs/INSTALL.md, docs/FAQ.md, docs/RESOURCES.md and docs/DOCKER-COMPAT.md, covering boards, WSL2 and Docker compatibility in more depth.

How solid is it

Kern's own numbers come from a single benchmark script, examples/benchmark.py, that the project tells readers to run themselves; on the author's test machine, an Intel i7-14700KF running Linux 7.0.0 with the release binary, it starts 3,000 boxes in about 2.2 seconds at roughly 0.3 MB of memory per running box, and the project states plainly that results will differ by CPU, kernel and filesystem. That is a useful order-of-magnitude signal, not an independently verified benchmark: the source draws no comparison numbers against Docker, Podman, gVisor, Firecracker, bubblewrap, youki or E2B, though it names all of them for context. The project is otherwise unusually candid about its own limits: its SECURITY.md states, ahead of any other claim in that document, that its isolation rests on an unprivileged user namespace, which it calls a fertile source of kernel LPE bugs, and its docs separately flag that a vgpio: pin list is cooperative metadata rather than an enforced boundary. No CVE count or audit history is cited for that user-namespace approach. The source gives kern no license, price, version number or release date, and no adoption numbers: no star count, download count or testimonials appear in the text. As a signal of very early traction, this was a same-day Show HN submission that had drawn 16 points and no comments at the time this was written.

Risks and caveats

Kern is explicit that it is not a hypervisor: its isolation boundary is the Linux kernel itself, so a kernel privilege-escalation bug is a full escape, a condition it says Docker and Podman share too and the reason it gives for why tools such as gVisor and Firecracker exist. Its rootless model rests on an unprivileged user namespace, which its own SECURITY.md calls a fertile source of kernel LPE bugs, stated ahead of any other claim in that document. It is not a boundary around whatever a user chooses to mount in: -v $HOME:/host hands a box the user's home directory outright, and --net host or --privileged are named opt-outs rather than incidents kern prevents; the only path it refuses to let a user bind into a box is its own runtime registry. The vgpio: device profile is chip-granular, not per-line: naming a specific pin does not actually confine a box to that pin, since the kernel exposes the whole /dev/gpiochipN device once any line on it is requested. The project states plainly that kern is not built for hostile code from strangers or for multi-tenant hosting on a kernel shared with other tenants, only for code the user already chose to run. And the retrieved text itself is truncated mid-sentence at the end of a benchmarking section called Two honest notes, so the latency figure it was building to, and the rest of that comparison, could not be retold here.

“The boundary is the Linux kernel, so a kernel privilege-escalation bug is an escape.”

— kern's README (security notes)