User:Zen desu/Container Creation

From Gentoo Wiki
Jump to:navigation Jump to:search

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


sys-process/tini is a simple init system designed for use in Docker containers.

Snapshot creation

root #btrfs subvol snap gentoo_base gentoo_tini


root #emerge --root ./gentoo_tini tini

RO Snapshot creation

root #btrfs subvol snap -r gentoo_tini .gentoo_tini_20230826


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:

FILE $PWD/gentoo_openrc/etc/inittab
#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

rc keyword selection

In the container's /etc/rc.conf, set rc_sys to lxc:

FILE $PWD/gentoo_openrc/etc/rc.conf

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:

FILE ~/.local/share/lxc/unbound/config
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.