Instant MicroVMs/Unikernels for macOS and Linux
linux unikernel unikraft osv freebsd netbsd microvm libkrun
README.md

Python on Unikraft #

A CPython HTTP service running as a Unikraft unikernel, built with bsdkrun pack.

There is no Dockerfile, no Kraftfile and no build.sh here — pack detects the project and generates all three internally.

Build #

bsdkrun pack .

Run #

bsdkrun unikraft . --cmdline "python -- /opt/python/bin/python3 -u /src/main.py"

pack prints that exact command when it finishes, so there is no need to remember it.

Try it #

curl http://<vm-ip>:8080/
{
  "message": "Hello from Python on Unikraft!",
  "python": "3.12.11",
  "machine": "arm64",
  "path": "/"
}

How the interpreter gets there #

Unlike the other interpreted examples here, this one does not start from an official language image. pack's Python provider installs the interpreter with mise into a single prefix, /opt/python, and copies that prefix into the rootfs whole.

That matters because Python finds its own standard library relative to the executable: bin/python3 implies lib/python3.x/ beside it. Splitting the interpreter across /usr/bin and /usr/lib, the way the Ruby and PHP providers do, would leave it unable to locate its own os.py.

mise's builds help twice over. They come precompiled, so no C toolchain is needed in the build image, and they link OpenSSL, SQLite and zlib statically — so what lands in the rootfs is that one prefix plus libc, instead of a scatter of system libraries.

The version comes from mise.toml. A .tool-versions file works too, as does no pin at all (3.12 by default).

Dependencies #

This example is deliberately stdlib-only, so it has nothing to install. A real project's manifest is picked up automatically, most-specific first:

File Installed with
uv.lock uv export → uv pip install
Pipfile / Pipfile.lock pipenv requirements → uv pip install
pyproject.toml uv pip install .
requirements.txt uv pip install -r

Packages install into /opt/python's own site-packages rather than a virtualenv — one prefix for the guest to find, not two.

Guest environment #

The provider sets three variables in the generated Kraftfile:

Variable Why
PYTHONHOME Points at /opt/python, so the prefix needs no deducing
PYTHONUNBUFFERED Buffered output on a serial console is lost in a crash
PYTHONDONTWRITEBYTECODE The rootfs is a read-only ramdisk; a .pyc write can only fail