Skip to content

Instantly share code, notes, and snippets.

What would you like to do?

systemd containers


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!

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


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 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

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 > /tmp/salt
$ cat > /tmp/ <<EOF
set -x
echo -e '\nn\n\n\n\n\n' | mysql_secure_installation
mysql <<END
GRANT ALL PRIVILEGES ON wordpress.* TO 'wordpress'@'%' IDENTIFIED BY '$password';
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" \\
cd /tmp
csplit /etc/wordpress/wp-config.php "/\/\*\*#@-\*\//"
cat xx00 salt xx01 > /etc/wordpress/wp-config.php
rm xx00 salt xx01

Container configuration

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

Wordpress installation process

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



This comment has been minimized.

Copy link

@Germano0 Germano0 commented Jan 25, 2017

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


This comment has been minimized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment