Docker Container werden ja immer beliebter aber leider gibt es keine direkte Unterstützung für FreeBSD. Auch sind leider richtig gute Open Source Projekte "Docker only" und beschreiben noch nicht mal mehr eine manuelle Installation, was die Portierung und den Betrieb in FreeBSD/Jails erschwert. Mit der richtigen, vor allem schlanken, Linux Distribution ist aber auch das kein Problem und ermöglicht mit dem folgenden Aufbau auf Basis der bereits vorbereiten BHYVE Virtualisierung einen Jail artigen Betrieb unter FreeBSD.
Es gibt seit FreeBSD 14 eine experimentelle Unterstützung für Podman, welches dann nativ Docker Container ausführen kann. Das könnte in Zukunft noch eine echte Alternative werden, aber ich beleuchte hier erst mal den "stabilen" Ansatz. Vielleicht wird der ja dann überflüssig. Schön wäre das.
Das Ziel ist ein System, welches die Daten, bzw. Konfiguration vom System bzw. der VM trennt und damit komplett unabhängig ist, ohne dabei allzu sehr in die von den Projekten bereitgestellten Docker Compose Dateien eingreifen zu müssen. Ganz so, was ich eigentlich bei den nativen FreeBSD Jails sehr schätze.
Hier haben wir nur den "Schmerz" einer, dafür aber sehr schlanken, Virtualisierung. Das fällt heutzutage aber kaum noch ins Gewicht und ich habe damit durchaus meinen Frieden gemacht. Schlank bedeutet, das wir auch auf "Extras" wie grafische Oberflächen oder VNC Konsolen verzichten. Pure Konsole.
NEU: Für ganz ungeduldige habe ich einen "Konsole only" Abschnitt. Da gibt es nur Befehle, keine Erklärungen.
Letzte Aktualisierung:
virtio-9p
/usr/local/bhyve/docker/root
. docker
wird der Name der VM. Also nur das sehr schlanke Basissystem, was Updates sehr einfach macht und lassen mit 16GB etwas Luft für die Docker Images. Aber keine Angst, die 16 GB werden nicht direkt zugeweisen. Durch sparse-zvol
ist das ZVol auf dem Host System nur so groß, wie Daten drin liegen. Am Anfang sind das weniger als 100 MB./opt/docker
abgelegt und mittels NFS
nach /usr/local/bhyve/data/docker
verbunden.Warum nicht das /var/lib/docker
Verzeichnis komplett "rauslegen"? Docker arbeitet mit sogenannten "Overlay Images" um Platz zu sparen, was nicht per NFS funktioniert. Ohne Overlay hätten wiederkehrende Docker Images auch wiederkehrenden Platzbedarf.
Warum nicht alles in /usr/local/bhyve/docker
ablegen? Wird die VM mit vm destroy docker
entfernt, wird das komplette Dataset inkl. aller Unterordner entfernt, AUCH wenn manuell drunter Datasets hinzugefügt wurden. Böse Falle! Daher gibt es das Verzeichnis /usr/local/bhyve/data
, genauso, wie das auch bei /usr/local/bastille/data
in den anderen Jails Artikeln gemacht wird.
Damit sieht das Setup so aus:
┌───────────────────────────────────────────────────────┐
│ FreeBSD: │
│ ┌────────────────────┐ │
│ │ VM: docker │ │
│ │ / ───────────────┼─► /usr/local/bhyve/docker/root │
│ │ /opt/docker ─────┼─► /usr/local/bhyve/data/docker │
│ └────────────────────┘ │
└───────────────────────────────────────────────────────┘
Ich gehe hier nur auf einen "Grundbetrieb" ein, der für normale und heimische Installationen für eine handvoll Benutzer ausreichen wird. Bei Anwendungen, die darüber hinaus gehen, müssen die Themen CPU, RAM und SWAP nochmal genauer betrachtet und ggf. angepasst werden. Auch kann sicherlich noch das ein oder andere Verzeichnis zusätzlich nach außen gelegt werden.
Optional: Wenn der zusätzliche data
Pool genutzt werden soll, dann kann dieser mit zfs create -o mountpoint=/usr/local/bhyve/data data/byhve
mit angelegt werden. Die Verzeichnisstruktur per zfs list | grep bhyve
sieht dann so aus:
# zfs list | grep bhyve
data/byhve 96K 1.75T 96K /usr/local/bhyve/data
work/bhyve 96K 893G 96K /usr/local/bhyve/
Als erstes legen wir für Alpine Linux mit ee /usr/local/bhyve/.templates/alpine.conf
ein Template an, was die Standards der VM festlegt. memory
und disk0_size
bei Erstellung angegeben
loader="uefi" # UEFI boot loader
cpu=2 # 2 CPUs
network0_type="virtio-net" # Virtio network driver
network0_switch="public" # Name of the Switch
disk0_type="virtio-blk" # Virtio storage driver (sata)
disk0_dev="sparse-zvol" # Use growing ZVOLs
disk0_name="root" # ZFS Volume name in /tank/bhyve/NAME
grub_install0="linux /boot/vmlinuz-virt initrd=/boot/initramfs-virt alpine_dev=cdrom:iso9660 modules=loop,squashfs,sd-mod,usb-storage,sr-mod"
grub_install1="initrd /boot/initramfs-virt"
vm iso https://dl-cdn.alpinelinux.org/alpine/v3.20/releases/x86_64/alpine-virt-3.20.3-x86_64.iso
heruntergeladen. Die aktuelle Version hier nachschauen und ggf. den Link anpassen.Die eigentliche Erstellung der VM ist dann mit vm create -s 16G -t alpine docker
schnell erledigt und gefolgt von einem vm install docker alpine-virt-3.20.3-x86_64.iso
wird die VM von der heruntergeladenen ISO gestartet. Tut euch aber selber einen gefallen und ruft vm console docker
in einer zweiten parallelen Shell auf:
root
einloggen ( Kein Passwort)setup-alpine
die Installation starten. Wenn ich nichts angebe, einfach mit Enter weiter springen:
docker.bsdbox.local
123
Europe/Berlin
none
openssh
yes
vda
sys
halt
das System beendenTipp: Die vm console
kann mit der Tastenfolge Enter ~ ~ .
beendet werden
Damit ist die Installation fertig und das installierte System kann nun mit vm start docker
final gestartet werden. Mit vm console docker
wird eine Konsole eröffnet (besser in einer zweite Shell) und es erscheint der typische Login von Linux.
Tipp: Wer sich die IP Adresse bei der Installation gemerkt hat, kann alternativ ab hier mit zwei SSH Shells arbeiten.
zfs create data/bhyve/docker
zfs set sharenfs="maproot=root:wheel,network=192.168.1.12/32" data/bhyve/docker
zfs get sharenfs data/bhyve/docker # Order und Unterordner teilen (wird vererbt)
zfs unshare -a
zfs share -a
Nun per root
einloggen und mit mkdir /opt/docker
das Datenverzeichnis erstellen, in der wir das extern liegende /usr/local/bhyve/data/docker
einbinden wollen. Dazu wird mit vi /etc/fstab
die fstab um folgenden Eintrag erweitert:
coretwo:/usr/local/bhyve/data/docker /opt nfs4 rw 0 0
Mit mount -a
wird alles, was in der /etc/fstab
steht, auch ohne Neustart eingebunden.
Docker selber ist nach der ganzen Vorarbeit dann eigentlich schnell konfiguriert und gestartet:
setup-apkrepos -cf # Paketquellen ermitteln
apk update # Paket Datenbank aktualisieren
apk upgrade --available # Pakete aktualisieren
apk add docker docker-cli-compose # Docker installieren
rc-update add docker default # Docker automatisch starten
service docker start # Docker starten
Mit einem reboot
kann und sollte noch geprüft werden ob alles nach einem Neustart klappt:
docker ps
geprüft werden./opt/docker/
ist eingebunden. Das kann mit mount | grep docker
geprüft werden.Neben dem Snapshot der ZFS Datasets kann auch ein komplettes Backup als TAR-Archiv erstellt werden. Das Archiv enthält die Konfigurations-Dateien und die Daten der Docker Container. Das ist ideal, um es (am besten verschlüsselt) extern zu sichern. Nun müssen wir noch entscheiden, wo das Archiv gespeichert werden soll. Hier verwenden wir das Verzeichnis /opt/docker/backup
, welches von außerhalb des VM gemountet wurde. Damit sind die Backups sofort unabhängig gespeichert und können dann über Snapshots wieder separat gesichert und weiterverarbeitet werden.
Ein manuelles Backup wird mit einem Befehl ausgeführt, insbesondere vor einem Update:
mkdir /opt/docker/backup/
tar -cpzf /opt/docker/backup/APPNAME_`date +%Y%m%d`.tar.gz /opt/docker/APPNAME/
Regelmäßige Backups sind das A und O einer Strategie, insbesondere wenn es sich um so wichtige Daten handelt. Das Aufräumen sollte auch in der VM selbst stattfinden, damit es nur ausgeführt wird, wenn die VM auch wirklich läuft. Ansonsten laufen die Backups leer.
vi /etc/crontabs/root
# House keeping
10 22 * * * root "find /opt/docker/backup/ -type f -mtime +30d -delete"
# APPNAME backup
0 22 * * * root "tar -cpzhf /opt/docker/backup/APPNAME_'$(date +\%Y\%m\%d)'.tar.gz /opt/docker/APPNAME"
cd /opt/docker/APPNAME
docker-compose stop # Dienst stoppen
docker-compose pull # Neue Images herunterladen
docker-compose up --force-recreate --build -d # Dienst neu erstellen
docker image prune -f # Alte Images entfernen
zfs create -p zroot/bhyve_data/docker
vm iso https://dl-cdn.alpinelinux.org/alpine/v3.20/releases/x86_64/alpine-virt-3.20.3-x86_64.iso
ee /zroot/bhyve/.templates/alpine.conf # Siehe oben
vm create -t alpine docker
vm install docker alpine-virt-3.20.3-x86_64.iso
# In einer zweiten parallelen Shell
vm console docker
setup-alpine # Siehe oben
# In der ersten Shell
vm restart docker
# In einer zweiten parallelen Shell oder per SSH
vm console docker # oder ssh root@DOCKERHOST
mkdir /opt/docker
echo 'docker /opt/docker 9p trans=virtio,rw 0 0' >> /etc/fstab
mount -a
setup-apkrepos -cf
apk update
apk upgrade --available
apk add docker docker-cli-compose
rc-update add docker default
service docker start
reboot
Voilá