Running containers using systemd-nspawn

After a visit to the talk about “containers and systemd” by Lennart Poettering, I just tried to set up several container setups using systemd-nspawn.

Test environment:

  • Fedora 22 for host
  • Fedora 21 for containers
  • Systemd 223

First, on the host, install a container system under a directory, let’s say, “/srv”.

host$ sudo mkdir -p /srv/ctf1
host$ sudo dnf -y --releasever=21 --nogpg --installroot=/srv/ctf1 \
      --disablerepo='*' --enablerepo=fedora install \
      systemd passwd dnf fedora-release bridge-utils iproute iputils less net-tools vim-minimal 
Fedora 21 - x86_64                                                            3.3 MB/s |  39 MB     00:12
Last metadata expiration check performed 0:00:19 ago on Fri Jul 31 17:44:52 2015.
Dependencies resolved.
...
Install  145 Packages
Total download size: 68 M
Installed size: 307 M
Downloading Packages:
...

Then it install a minimal set of Fedora 21 system under /srv/ctf1.

Now you should reset a root password to be able to log in to container with root. Edit /srv/ctf1/etc/passwd like that:

root::0:0:root:/root:/bin/bash

Then run a container:

host$ sudo systemd-nspawn -bD /srv/ctf1
Spawning container ctf1 on /srv/ctf1.
Press ^] three times within 1s to kill container.
systemd 223 running in system mode. (+PAM +AUDIT +SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ -LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD +IDN )
Detected virtualization 'systemd-nspawn'.
Detected architecture 'x86-64'.

Welcome to Fedora 21 (Twenty One)!

Option “-b” allows the container to boot, otherwise it won’t repeat the whole boot process, which results merely in an isolated environment like a chroot-ed one. Option -D sets the root directory of container.

Without an “-n” option like above, systemd-nspawn will share network interfaces from the host to the container, to allow container users to be connected with the network. However, that would not be applicable for most use cases.
To be able to set up network interfaces for each container, you want to run it with “-n” option.

host$ sudo systemd-nspawn -bnD /srv/ctf1

And don’t forget to enable networkd and resolved inside the container:

container# systemctl enable systemd-networkd
container# systemctl start systemd-networkd
container# systemctl enable systemd-resolved
container# systemctl start systemd-resolved

Then you could see a new network interface like below:

container# ip a
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: host0@if4:  mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 1a:d5:67:03:d1:dc brd ff:ff:ff:ff:ff:ff

To be able to bind host and containers using a bridge interface:

host$ cat /etc/systemd/network/br0.netdev
[NetDev]
Name=br0
Kind=bridge

host$ cat /etc/systemd/network/br0.network
[Match]
Name=br0

[Network]
DHCP=yes

host$ cat /etc/systemd/network/eth0.network
[Match]
Virtualization=container
Name=eth0*

[Network]
Bridge=br0

host$ sudo systemd-nspawn --network-bridge -bnD /srv/ctf1

Then you can see, the container’s interface belongs to a bridge interface, so that the container can be reachable.

host$ brctl show
bridge name     bridge id               STP enabled     interfaces
br0             8000.ee15c236c35d       no              eth0
                                                        vb-ctf1

Share Button
  • nadrimajstor

    Nice simple systemd-nspawn primer. I would use:

    container# systemctl --now enable systemd-networkd.service systemd-resolved.service

    Though, not sure if that would improve readability (lazy sysadmin) 🙂