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