systemd-nspawn is a surprisingly powerful and lightweight containerization tool that leverages the existing systemd infrastructure to run isolated environments.
Let’s see it in action. Imagine you want to spin up a minimal Debian container to test some package.
First, you’ll need a root filesystem for your container. You can download a pre-built one or create your own. For this example, let’s assume you have a Debian rootfs at /srv/my-debian-container.
sudo systemd-nspawn -D /srv/my-debian-container
This command starts an interactive shell inside the container. You’re now root within this isolated environment. Notice that systemd is also running inside, managing services just like on your host. You can install packages, run commands, and even reboot the container, all from within this nspawn session.
To exit, simply type exit.
The core problem systemd-nspawn solves is providing a simple, yet robust, way to run isolated user-space environments without the overhead of full virtualization or complex external tools. It’s not about abstracting hardware; it’s about isolating processes and their dependencies.
Internally, systemd-nspawn utilizes Linux kernel features like namespaces (PID, network, mount, UTS, IPC, user) to create the isolation. It also leverages control groups (cgroups) for resource management. The -D flag tells nspawn which directory to use as the root filesystem for the container. It then starts a new systemd instance within this isolated environment.
You have several levers to control the container’s behavior:
-D /path/to/rootfs: Specifies the root filesystem directory. This is the most fundamental setting.--bind=/host/path:/container/path: Mounts a directory from the host into the container. This is crucial for sharing data or configuration. For example,--bind=/etc/resolv.conf:/etc/resolv.confwill share your host’s DNS settings.--network-veth: Creates a virtual network interface pair for the container, allowing it to have its own IP address and communicate on the network. Without this, the container shares the host’s network namespace.--private-users: Enables user namespace remapping, allowing users inside the container to be mapped to unprivileged users on the host, enhancing security.--machine=my-container-name: Assigns a machine name to the container, which can be used bysystemdtools likemachinectlfor management.--bind-mount=/path/on/host=/path/in/container: Similar to--bind, but specifically for mount points.
When you run sudo systemd-nspawn -D /srv/my-debian-container --network-veth --bind=/srv/shared-data:/data, the systemd process within the container sees /srv/my-debian-container as its / and has a new network interface. The /data directory inside the container is actually a direct link to /srv/shared-data on your host.
A common misconception is that systemd-nspawn requires a separate kernel. It doesn’t. It shares the host’s kernel, which is a significant part of its efficiency. The isolation is purely at the user-space level. This means you can’t run a different kernel version inside the container than what your host is running, but for most use cases, this is perfectly acceptable and simplifies management.
The next step in understanding systemd-nspawn is exploring how to manage these containers more effectively using machinectl.