Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?

systemd containers

Assumptions

This how-to uses mybox as container name, mkosi in order to create containers (it works for multiple distributions and has more features compared to dnf --installroot), and crudini for configurations file (you can use your preferred text editor instead).

How to create a container with mkosi

# mkosi --cache /var/cache/mkosi -d fedora -t directory -o /var/lib/machines/mybox

mkosi can do much more! https://github.com/systemd/mkosi

How to start a container with machinectl

# machinectl start mybox

How to invoke a shell

# machinectl shell mybox

How to configure the network with networkd

machinectl calls systemd-nspawn with different network connection defaults. The first creates a new virtual ethernet interface, while the second uses the loopback interface. This little how-to uses nspawn configuration files in order to setup containers instead of calling systemd-nspawn directly (this is necessary in order to boot containers with machinectl with custom settings). The configuration files can be stored under /etc/systemd/nspawn (not created by default), /run/systemd/nspawn and /var/lib/machines/, but only the first two paths are considered as trusted, so this how-to uses the second directory (source: nspawn.c source code). machinectl defaults are overridden by specific nspawn configuration files.

In order to see machinectl defaults:

$ crudini --get /usr/lib/systemd/system/systemd-nspawn@.service Service ExecStart

More information about nspawn configuration files: man systemd.nspawn

Loopback

If you want to use the loopback interface:

# crudini --set /run/systemd/nspawn/mybox.nspawn Network VirtualEthernet no
# machinectl stop mybox
# machinectl start mybox

Virtual ethernet interface

# crudini --set /run/systemd/nspawn/mybox.nspawn Network VirtualEthernet yes
# systemctl start systemd-networkd
# systemctl enable systemd-networkd
# systemctl -M mybox enable systemd-networkd
# machinectl stop mybox
# machinectl start mybox

Test your connection with ping -c 1 mybox Unable to ping your container? Have a look at https://www.freedesktop.org/software/systemd/man/nss-mymachines.html Still have problems? Try machinectl status mybox and networkctl

Network bridge

If libvirt-daemon-config-network is installed and libvirtd.service is running, you could use the existing bridge for your containers:

# crudini --set /run/systemd/nspawn/mybox.nspawn Network Bridge=virbr0
# systemctl start systemd-networkd
# systemctl enable systemd-networkd
# systemctl -M mybox enable systemd-networkd
# machinectl stop mybox
# machinectl start mybox

If you need to create a network bridge, please follow https://major.io/2015/03/26/creating-a-bridge-for-virtual-machines-using-systemd-networkd/

Limit CPU and memory usage

# systemctl set-property --runtime systemd-nspawn@mybox.service MemoryMax=500M
# systemctl set-property --runtime systemd-nspawn@mybox.service CPUShares=500

Configuration files are stored in /etc/systemd/system.control/systemd-nspawn@mybox.service.d/ More information about resource control: man systemd.resource-control

Boot container when host boots

# machinectl enable mybox

Example: Wordpress

Container creation

# mkosi --cache /var/cache/mkosi -d fedora -t directory -o /var/lib/machines/wordpress -p wordpress,mariadb-server
# crudini --set /run/systemd/nspawn/wordpress.nspawn Network VirtualEthernet no

Configuration script

Adjust port=8080 as you like (first line).

$ port=8080; password=$(openssl rand -base64 18)
$ curl https://api.wordpress.org/secret-key/1.1/salt/ > /tmp/salt
$ cat > /tmp/wordpress.sh <<EOF
#!/bin/sh
set -x
echo -e '\nn\n\n\n\n\n' | mysql_secure_installation
mysql <<END
CREATE DATABASE wordpress;
GRANT ALL PRIVILEGES ON wordpress.* TO 'wordpress'@'%' IDENTIFIED BY '$password';
FLUSH PRIVILEGES;
END
sed -i "s/Listen 80/Listen $port/" /etc/httpd/conf/httpd.conf
sed -i "s/Require local/Require all granted/" /etc/httpd/conf.d/wordpress.conf
multisite="define( 'WP_ALLOW_MULTISITE', true );"
sed -i \
    -e "s:database_name_here:wordpress:" \\
    -e "s:username_here:wordpress:" \\
    -e "s:password_here:$password:" \\
    -e "s:/\* That's all, stop editing! Happy blogging. \*/:$multisite\n&:" \\
    -e "/put your unique phrase here/d" \\
    /etc/wordpress/wp-config.php
cd /tmp
csplit /etc/wordpress/wp-config.php "/\/\*\*#@-\*\//"
cat xx00 salt xx01 > /etc/wordpress/wp-config.php
rm xx00 salt xx01 wordpress.sh
EOF

Container configuration

# machinectl start wordpress
# systemctl -M wordpress start mariadb
# machinectl copy-to wordpress /tmp/wordpress.sh
# machinectl copy-to wordpress /tmp/salt
# machinectl shell wordpress /bin/sh /tmp/wordpress.sh
# systemctl -M wordpress enable mariadb httpd
# systemctl -M wordpress start httpd
$ rm /tmp/wordpress.sh /tmp/salt

Wordpress installation process

Visit http://localhost:8080 and follow the procedure.

Resources

@Germano0

This comment has been minimized.

Copy link

commented Jan 25, 2017

This gist contains the best systemd containers use case example of the entire internet

@Germano0

This comment has been minimized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.