User:Zen desu/Container Creation
Personal guide for container creation using btrfs snapshots.
Base Image Creation
First, a snapshot for the base image must be created:
root #
btrfs subvol create gentoo_base
Then, emege --root can be used to build the base system in this subvolume:
root #
emerge --root ./gentoo_base baselayout sys-libs/glibc
With the base image created, a read-only snapshot can be created:
root #
btrfs subvol snapshot -r gentoo_base .gentoo_base_20230825
I add a date to the read-only snapshots and make them hidden, this is preference.
Debug Image
I generally do not include extra tools and shells in my containers, sometimes it's useful to create a debug image that contains them:
root #
btrfs subvol snapshot .gentoo_base_20230825 gentoo_debug
root #
emerge --root ./gentoo_debug coreutils bash iproute2
Init Image
tini
sys-process/tini is a simple init system designed for use in Docker containers.
Snapshot creation
root #
btrfs subvol snap gentoo_base gentoo_tini
Emerge
root #
emerge --root ./gentoo_tini tini
RO Snapshot creation
root #
btrfs subvol snap -r gentoo_tini .gentoo_tini_20230826
OpenRC
This is a poor choice for a container init. It's very heavy, has many dependencies, doesn't handle container shutdown signals by default, and does not run in user unprivileged containers as it expects mounts.
Using the base image subvolume a source, a new subvolume for the OpenRC image can be created:
root #
btrfs subvolume snapshot gentoo_base gentoo_openrc
Then OpenRC can be emerged there:
root #
emerge --root ./gentoo_openrc openrc coreutils grep app-alternatives/sh
sys-apps/grep, app-alternatives/sh, sys-apps/coreutils are part of @system, and are required by OpenRC.
inittab config
LXC has its own console system, agetty is not needed, so inittab lines for it can be removed.
Because lxc-stop sends a stop signal which Sysvinit does not process, the following must be added to the inittab:
# TERMINALS
#x1:12345:respawn:/sbin/agetty 38400 console linux
#c1:12345:respawn:/sbin/agetty --noclear 38400 tty1 linux
#c2:2345:respawn:/sbin/agetty 38400 tty2 linux
#c3:2345:respawn:/sbin/agetty 38400 tty3 linux
#c4:2345:respawn:/sbin/agetty 38400 tty4 linux
#c5:2345:respawn:/sbin/agetty 38400 tty5 linux
#c6:2345:respawn:/sbin/agetty 38400 tty6 linux
# For lxc-stop
pf:12345:powerwait:/sbin/halt
rc keyword selection
In the container's /etc/rc.conf, set rc_sys
to lxc:
rc_sys="lxc"
Like with the base image, a read-only snapshot can be created:
root #
btrfs subvolume snapshot -r gentoo_openrc/ .gentoo_openrc_20230825
Service Cleaning
Remove services which are not used:
- /etc/runlevels/boot/sysctl
- /etc/runlevels/boot/loopback
Service Image
Finally, a service can be added as a final layer over the init system:
root #
btrfs subvolume snapshot gentoo_tini gentoo_tini_unbound
root #
emerge --root ./gentoo_tini_unbound unbound
Container Packing
To pack the container, with -T setting the number of threads, and -<num> setting the compression level:
root #
tar -c -I 'xz -9 -T96' -f gentoo-tini-unbound.tar.xz -C gentoo_tini_unbound/ .
Container importing
root #
touch config
root #
tar -cJf empty_metadata.tar.xz config
user $
lxc-create -t local -n unbound -- --fstree gentoo-openrc-unbound.tar.xz --metadata empty_metadata.tar.xz
Init config
Once the container is imported, the init to be changed to use tini by setting:
lxc.init.cmd = /usr/bin/tini /usr/sbin/unbound -- -d
Although not required for unbound, changing the halt signal may be required for some containers
lxc.signal.halt = SIGINT
.