Lightweight container with systemd-nspawn
Container with systemd-nspawn
To install latest developer versions of any packagor program it is good practice not to pollute the installation with possibly experimental versions. One lightweight and not widely used way is to use systemd-nspawn
.
https://wiki.archlinux.org/index.php/Systemd-nspawn#Create_a_Debian_or_Ubuntu_environment
Originally developed for testing systemd itself this boots into a virtual filesystem, gives the container its own PID 1 and are bootet from the host by root (depending on the kernel config the container’s priviledges may then be dropped).
Networking can be an container’s own private network or the host’s network can be shared.
The filesystem from the host can be mounted.
After all Docker and also systemd-nspawn are just using the Linux kernel’s namespace and cgroups features.
How to create a container
cd /var/lib/container/
sudo debootstrap xenial qgis299 http://archive.ubuntu.com/ubuntu/
The content of the directory afterwads:
$ ls qgis299/
bin dev home lib64 mnt proc run srv tmp var
boot etc lib media opt root sbin sys usr
Booting into the container first time (to set a root password):
sudo systemd-nspawn -D qgis299
passwd
logout
Then the container should be booted in the background and machinectl
used to e.g. enter it. The ArchLinux Wiki has (as usual) a very good overview and helpful troubleshooting tipps.
On the host:
With sudo systemctl edit systemd-nspawn@.service
enter in the newly created file
cat /etc/systemd/system/systemd-nspawn@.service.d/override.conf
[Service]
ExecStart=
ExecStart=/usr/bin/systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --machine=%I
Inside the container:
systemctl enable --now systemd-resolved
ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
How to Create a Cache for debootstrap
TL;DR Run curl -L https://slm.prdv.de/setup_debootstrapcache.sh | sudo sh
On Ubuntu 16.04 and possibly Debian the program apt-move
can be used to create a cache for frequent debootstrap
use. Possibly because the following was tested on Ubuntu 16.04 only, some paths may differ on Debian. As my usecase was to install QGIS 2.99 nigthly builds which seem to be provided quite reliably for xenial
this was all that the usecase asked for.
Following http://cheesehead-techblog.blogspot.de/2012/01/local-file-cache-to-speed-up.html this is resulting change:
sudo debootstrap --arch=amd64 xenial qgisbuilds http://archive.ubuntu.com/ubuntu/sudo debootstrap --no-check-gpg --arch=amd64 xenial qgisbuilds file:///var/local/mirrors
- install necessary packages
- create folders and helper files
- perform cache-warming and set up the mirror
- use
debootstrap
with a local mirror
install necessary packages
sudo apt-get apt-move
create folder and helper files
A dedicated folder to hold the cache is needed:
sudo mkdir -p /var/cache/mirrors
And also a config file needs to be created:
sudo tee "/var/lib/container/apt-move.conf" > /dev/null <<'EOF'
COPYONLY=yes
APTSITES="/all/"
LOCALDIR=${__LOCALCACHEDIR}
DIST=${__CODENAME}
PKGTYPE=binary
FILECACHE=/var/cache/apt/archives
LISTSTATE=/var/lib/apt/lists
DELETE=no
MAXDELETE=20
COPYONLY=yes
PKGCOMP=gzip
CONTENTS=no
GPGKEY=
EOF
Finally what is left to do is to create a primer for the Release file:
sudo tee "${__CONFDIR}/myapt.conf" > /dev/null <<'EOF'
APT::FTPArchive::Release {
Origin "APT-Move";
Label "APT-Move";
Suite "${__CODENAME}";
Codename "${__CODENAME}";
Architectures "amd64";
Components "main restricted universe";
Description "debootstrap mirror";
};
EOF
cache warming and mirror setup
sudo mkdir /tmp/cache
sudo debootstrap --arch=amd64 --download-only xenial /tmp/cache
sudo cp /tmp/cache/var/cache/apt/archives/* /var/cache/apt/archives/
Now a Packages and Release file must be generated containing info about this mirror:
cd /var/cache/mirror
sudo apt-ftparchive packages pool/main/ | gzip -9c > /tmp/Packages.gz
sudo mv /tmp/Packages.gz dists/xenial/main/binary-amd64/Packages.gz
sudo apt-ftparchive -c /var/lib/container/myapt.conf release dists/xenial/ > /tmp/Release
sudo mv /tmp/Release dists/xenial/
sample qgisbuilds
On Debian and Ubuntu the program debootstrap
downloads a root filesystem that can be entered or booted with systemd-nspawn
. Some workarounds to execeute initial commands on first boot can easily set up a working QGIS build server.
A script doing all these tasks is available at /application/physical/scripts/spinup-qgis-build-container.sh , here are some interstings snippets:
use the above created mirror to bootstrap in a bandwidth-saving way
sudo debootstrap --no-check-gpg xenial FOOBAR file:///var/local/mirrors
Add a check to /etc/rc.local to execute a file somewhere else to be run only once.
sudo tee "./FOOBAR/etc/rc.local" > /dev/null <<'EOF'
#!/bin/sh -e
if [ -f /root/firstboot.sh ]; then /bin/bash "/root/firstboot.sh" && rm "/root/firstboot.sh"; fi
exit 0
EOF
Manipulate the apt sources:
sudo tee "./FOOBAR/etc/apt/sources.list" > /dev/null <<'EOF'
deb http://archive.ubuntu.com/ubuntu xenial main
deb http://archive.ubuntu.com/ubuntu xenial universe
deb http://qgis.org/ubuntugis-nightly xenial main
#deb-src http://qgis.org/ubuntugis-nightly xenial main
deb http://ppa.launchpad.net/ubuntugis/ubuntugis-unstable/ubuntu xenial main
EOF
Add a hostname
sudo tee "./FOOBAR/etc/hostname" > /dev/null <<'EOF'
qgisbuilds
EOF
sudo tee "./FOOBAR/root/firstboot.sh" > /dev/null <<'EOF'
systemctl enable --now systemd-networkd systemd-resolved
ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
apt-get update
apt-get -y upgrade
id -u user &>/dev/null || adduser -q --disabled-password --gecos '' --ingroup sudo --uid 1976 user
echo 'user:user' | chpasswd
su - user
export HOME=/home/user
echo 'export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${HOME}/apps/lib/' >> .profile
#continue to set up local QGIS build