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