nspawn

Docker-like management of systemd-nspawn machines. Images from an OCI hub, shared layers, and systemd all the way down.

nspawn pulls OCI images from the hub at hub.nspawn.org, from Docker Hub or from any other registry, stores them as shared layers and starts, inspects and stops the machines through the D-Bus APIs of systemd-machined and systemd itself. No daemon of its own, no machinectl, no importctl: the machines are ordinary systemd-nspawn@.service units that the rest of the system already knows.

Images from any registry

nspawn search fedora looks on the hub and on Docker Hub at once; nspawn pull fetches from either, and login keeps credentials per registry. Layers are downloaded once, verified against their digests and shared between machines. Remove an image and the layers nobody uses go with it.

Images and the hub

Machines and apps

Images that ship systemd boot like machinectl start does. Anything else, for example a docker image, runs its entrypoint as an app under a stub init, with -p, -e, -v and --entrypoint as in docker. ps, exec, shell, logs and stop work the same on both.

Running machines

Networking that works everywhere

A docker0 style bridge with NAT, fixed addresses, published ports and machine names that resolve, managed by nspawn itself. It behaves the same whether the host runs systemd-networkd, NetworkManager, docker, firewalld or nothing at all.

Networking

The whole tool in a screenful

nspawn hub ls                     # repositories and tags on the hub
nspawn search fedora              # images on the hub and on Docker Hub
sudo nspawn login docker.io -u me # credentials for a registry (the hub by default)
sudo nspawn pull fedora:44        # download and assemble an image
nspawn images ls                  # local images (all of them, not only ours)
sudo nspawn start fedora-44       # boot it as a machine
sudo nspawn create fedora-44 db   # another machine from the same image
sudo nspawn start web -p 8080:80 -e KEY=v -v /srv/data:/data -v pgdata:/var/lib/pg
nspawn ps                         # running machines: image, mode, command, uptime
nspawn exec fedora-44 -- systemctl is-system-running
nspawn shell fedora-44
nspawn logs fedora-44             # console output; --inside reads its journal
sudo nspawn stop fedora-44
sudo nspawn images rm fedora-44   # also frees layers and blobs nobody uses

sudo nspawn build -t team/app:1 ./app   # mkosi --format=oci, imported as an image
nspawn push team/app:1                  # upload it; layers already there are skipped

Build with mkosi, push anywhere

nspawn build runs mkosi with --format=oci on a directory with a mkosi.conf, imports the result as a local image and push uploads it to the hub or to any registry you point it at.

Building images

Open images

Every image on the hub is built from public mkosi definitions with the distribution’s own package manager. Read them, rebuild them, send fixes.

mkosi definitions

Small and self-contained

One binary, written in Rust. Its state lives under /var/lib/nspawn, its machines under /var/lib/machines, and everything it generates is a plain systemd unit or settings file you can read.

How it fits together