FreeBSD Jails vs. Docker: Die wichtigsten Unterschiede
FreeBSD Jails nutzen ein vollständiges Userland, Docker geschichtete Images. Vergleichen Sie Software, Zustand, Netzwerk und Grenzen beider Modelle.
FreeBSD Jails und Docker-Container in einem Absatz
FreeBSD Jails und Docker-Container lösen dasselbe Problem in zwei unterschiedlichen Formen. Beide führen isolierte Userlands auf einem gemeinsamen Kernel aus. Keines von beiden ist daher eine virtuelle Maschine. Der Unterschied liegt darin, was jeweils enthalten ist. Ein Docker-Container führt einen Prozess aus einem geschichteten Image aus, das Sie aus einer Registry geladen haben. Ein Jail führt ein vollständiges FreeBSD-Userland aus: mit eigenem /etc, eigenen rc-Startskripten, eigener pkg-Datenbank und beliebig vielen Prozessen. Fast alle weiteren Unterschiede auf dieser Seite ergeben sich daraus.
SSD Nodes bietet keine FreeBSD-Images an. Sie können auf dieser Plattform keinen FreeBSD-Server mieten, und der folgende Text ist keine Installationsanleitung für eine Maschine, die Sie hier kaufen können. Es handelt sich um einen Vergleich zweier Isolationsmodelle. Er soll Ihnen zeigen, welches Modell ein Workload tatsächlich benötigt, und Ihnen ermöglichen, die Konfiguration eines FreeBSD-Teams zu verstehen, ohne raten zu müssen.
Was ein Jail tatsächlich ist
Jails wurden im März 2000 mit FreeBSD 4.0 eingeführt. Damit sind sie älter als cgroups und ungefähr ein Jahrzehnt älter als Docker. Der Mechanismus besteht aus einem Kernel-Aufruf. jail(8) übernimmt einen Verzeichnisbaum und startet darin Prozesse mit einer zugewiesenen Jail-ID. Der Kernel verweigert anschließend eine festgelegte Gruppe von Operationen für jeden Prozess mit dieser ID. Ein Prozess in einem Jail kann keine Prozesse außerhalb seines Jails sehen. Er kann keine Dateisysteme mounten oder unmounten, keine Kernel-Module laden und nicht an Netzwerkadressen binden, die dem Jail nicht zugewiesen wurden. Sie müssen keinen separaten Namespace-Typ erlernen. Es gibt auch keine Aktivierung einzelner Funktionen pro Feature. Die Einschränkungen werden als Einheit angewendet und über Parameter in der Jail-Konfiguration angepasst.
Auf dem Host listet jls die laufenden Jails auf. jexec web sh öffnet eine Shell innerhalb des Jails mit dem Namen web.
Sie erstellen ein Jail, indem Sie eine FreeBSD-Userland-Umgebung in ein Verzeichnis legen. Das Basissystem erledigt dies für Sie:
sudo bsdinstall jail /usr/local/jails/containers/webDamit wird der Basissatz für Ihr Release abgerufen und die üblichen Schritte nach der Installation werden ausgeführt. Sie legen also ein root-Passwort fest und wählen eine Zeitzone, genau wie bei einem neuen Server. Das Ergebnis ist eine FreeBSD-Installation in einem Verzeichnis. Anschließend beschreiben Sie sie in /etc/jail.conf:
web {
host.hostname = "web.example.internal";
path = "/usr/local/jails/containers/web";
ip4.addr = "10.0.0.10";
exec.start = "/bin/sh /etc/rc";
exec.stop = "/bin/sh /etc/rc.shutdown";
mount.devfs;
}Starten Sie das Jail und prüfen Sie es anschließend:
sudo service jail start web
jlsjls sollte nun web mit einer JID, seinem Hostnamen und seiner IP-Adresse auflisten. Wenn das Jail nicht angezeigt wird, führen Sie direkt sudo jail -c web aus. Der Befehl wendet dieselbe Konfiguration im Vordergrund an und gibt den Parameter aus, den er nicht akzeptieren konnte, anstatt den Fehler nur in der Dienstausgabe zu hinterlassen.
Die Zeile, die Sie zweimal lesen sollten, ist exec.start = "/bin/sh /etc/rc". Beim Start eines Jails wird das normale Boot-Skript von FreeBSD darin ausgeführt. Dadurch startet das Jail jeden Dienst, der in seinem eigenen /etc/rc.conf aktiviert ist. Für einen Docker-Container gibt es keinen entsprechenden Schritt. Er führt den Entrypoint-Prozess des Images aus und wird beendet, sobald dieser Prozess endet.
Wie Sie Software beziehen: Images und Registries im Vergleich zu einem selbst befüllten Userland
Diesen Unterschied bemerken Sie bereits am ersten Tag.
Bei Docker geben Sie die Software an und erhalten sie. docker pull nginx ruft ein geschichtetes, inhaltsadressiertes Image ab, das jemand anderes erstellt und getestet hat. docker compose up -d startet es mit eingebundenen Volumes und angebundenem Netzwerk. Die Registry ist das Produkt. Der größte Vorteil eines Docker-Workflows besteht darin, dass Tausende Projekte ein funktionierendes Image veröffentlichen. Dadurch wird Docker auf einem VPS auszuführen zu einer kurzen Aufgabe statt zu einem eigenen Projekt.
FreeBSD liefert keine standardmäßige öffentliche Registry für Jail-Images mit. Sie erstellen ein leeres Userland und installieren die Software darin, genauso wie Sie einen Bare-Metal-Server einrichten würden. Das bedeutet mehr Eingaben. Es ist aber auch transparenter, weil in der Jail genau das läuft, was pkg dort installiert hat, und zwar aus demselben Paketsatz, den auch der Host verwendet.
Die Werkzeuge machen den Vorgang kurz. BastilleBSD ist der verbreitete Jail-Manager und als Paket verfügbar:
sudo pkg install bastille
sudo sysrc bastille_enable=YES
sudo bastille setup
sudo bastille bootstrap 15.1-RELEASEbastille setup konfiguriert Netzwerk, Speicher und Firewall für Sie. bastille bootstrap lädt ein Release einmal herunter. Jede danach erstellte Jail verwendet es wieder. FreeBSD 15.1 ist das aktuelle Produktions-Release und wurde im Juni 2026 veröffentlicht. Ersetzen Sie es durch das Release, das Sie einsetzen.
Eine Jail zu erstellen ist dann ein Befehl. Sie anschließend zu befüllen ist ein weiterer:
sudo bastille create web 15.1-RELEASE 10.17.89.10/24
sudo bastille pkg web install nginx
sudo bastille service web nginx start
sudo bastille console webbastille console web öffnet eine Login-Shell innerhalb der Jail. bastille list zeigt, was auf dem Host vorhanden ist. Für reproduzierbare Builds enthalten Bastille-Templates die einzelnen Schritte in einer Datei und wenden sie auf eine Jail an. Das ist das, was einer Dockerfile in dieser Welt am nächsten kommt. Ein Template wird für jede Jail erneut ausgeführt. Nichts wird vorab fertig installiert.
Die ehrliche Zusammenfassung ist daher kurz: Docker stellt Ihnen Builds anderer bereit. Jails geben Ihnen Ihre eigenen Installationen. Wenn die Software auf Ihrer Auswahlliste als Container-Image und in keiner anderen Form veröffentlicht wird, ist die Frage damit entschieden, bevor andere Kriterien berücksichtigt werden.
Status und Upgrades: der Teil, den ZFS verändert
Docker trennt den Status absichtlich. Das Container-Dateisystem ist verwerfbar. Ihre Daten liegen in einem benannten Volume oder einem Bind-Mount. Ein Upgrade besteht aus docker compose pull gefolgt von docker compose up -d. Der Container wird ersetzt. Alles, was Sie nicht in einem Volume abgelegt haben, ist weg. Das ist ein Vorteil, wenn Sie diese Regel einhalten, und ein Datenverlust, wenn Sie sie vergessen. Deshalb ist die Wahl zwischen Bind-Mounts und benannten Volumes in einem Compose-Stack so wichtig.
Ein Jail trennt den Status nicht. ZFS macht dieses Modell möglich. Das gesamte Jail ist ein Dataset:
sudo zfs snapshot zroot/jails/containers/web@pre-upgrade
sudo pkg -j web upgrade
sudo zfs rollback zroot/jails/containers/web@pre-upgradePrüfen Sie den tatsächlichen Dataset-Namen mit zfs list, bevor Sie diesen Befehl ausführen. Der Pfad oben entspricht der vom Handbook verwendeten Struktur. Der Snapshot ist nach etwa einer Sekunde erstellt und benötigt zunächst fast keinen zusätzlichen Speicher. Erst wenn sich der Inhalt des Jails ändert, steigt der Speicherbedarf. Falls das Upgrade den Dienst beschädigt, setzt der Rollback die gesamte Userland-Umgebung auf ihren vorherigen Stand zurück. Das umfasst auch die Paketdatenbank und die Konfigurationsdateien, die Sie um 2 Uhr morgens manuell bearbeitet haben. Docker bietet dafür kein integriertes Gegenstück, weil sein Modell davon ausgeht, dass Sie einen solchen Mechanismus nicht benötigen.
zfs clone ist die andere Hälfte. Ein Klon eines Snapshots ist ein neues, beschreibbares Jail. Es verwendet unveränderte Blöcke gemeinsam mit dem übergeordneten Dataset. Eine Staging-Kopie eines 3-GB-Jails benötigt daher auf dem Datenträger fast keinen zusätzlichen Speicher, solange Sie nichts daran ändern. So erstellt ein FreeBSD-Administrator ein Jail mit dem Zustand „wie in der Produktion“, um ein Upgrade zu testen.
Das Upgrade des Basissystems ist von den Paketen getrennt. Für ein Jail mit einer eigenen Kopie der Userland-Umgebung:
sudo freebsd-update -b /usr/local/jails/containers/web fetch installThin Jails vermeiden diese Arbeit. Sie binden eine gemeinsam verwendete, schreibgeschützte Basis über nullfs ein und geben jedem Jail eine eigene kleine beschreibbare Schicht. Dadurch patchen Sie die Basis einmal, und jedes Jail erhält das Ergebnis. Bastille erstellt standardmäßig Thin Jails.
Netzwerk: veröffentlichte Ports oder eine Entscheidung zur Adressierung
Docker legt die Netzwerkkonfiguration für Sie fest und fordert Sie auf, Ausnahmen zu veröffentlichen. Container werden an ein Bridge-Netzwerk angeschlossen, erreichen sich in einem benutzerdefinierten Netzwerk über den Dienstnamen, und -p 8080:80 macht einen von ihnen für den Host erreichbar. Docker schreibt eigene Paketfilterregeln, um das zu ermöglichen. Auf diese Weise umgeht ein veröffentlichter Container-Port ufw direkt.
Bei einem Jail müssen Sie das Modell von Anfang an festlegen. Es gibt zwei Möglichkeiten.
Gemeinsame IP-Adresse. ip4.addr = "10.0.0.10" fügt diese Adresse zu einer vorhandenen Host-Schnittstelle hinzu und beschränkt das Jail darauf. Das Jail hat keinen eigenen Netzwerk-Stack und kann daher keine eigene Firewall betreiben. Es kann auch nicht tatsächlich an jede Adresse binden: Ein Jail-Socket, der 0.0.0.0 anfordert, wird vom Kernel auf die eigene Adresse des Jails umgeschrieben. Zwei Jails können nicht beide Port 80 an derselben Adresse überwachen. Sie weisen daher jedem Jail eine eigene Adresse zu oder setzen einen Reverse Proxy davor.
VNET. Fügen Sie dem Jail vnet; hinzu. Dadurch erhält es einen vollständigen Netzwerk-Stack mit eigenen Schnittstellen, einer eigenen Routing-Tabelle und eigenen Firewall-Regeln. Sie verbinden es über ein epair mit dem Host. Dabei handelt es sich um ein virtuelles Kabel mit jeweils einem Ende auf beiden Seiten. Das Host-Ende wird an eine Bridge angeschlossen. Dies entspricht am ehesten der Netzwerkkonfiguration von Docker. Dieser Modus wird von Bastilles -V- und -B-Jail-Typen verwendet.
Die Weiterleitung eines Host-Ports in ein Jail erfolgt über eine pf-Redirect-Regel. Bastille kapselt diese Funktion:
sudo bastille rdr web tcp 80 80Es gibt kein EXPOSE und keine automatische Veröffentlichung von Ports. Nichts erreicht ein Jail, sofern seine Adresse oder eine Redirect-Regel dies nicht erlaubt. Der Start dauert dadurch länger, und die Firewall bleibt deutlich ruhiger.
Ressourcenlimits: cgroups im Vergleich zu rctl
Docker begrenzt einen Container mit cgroups. Die Limits befinden sich dort, wo der Container definiert ist: --memory=1g --cpus=1.5 in der Befehlszeile oder in den entsprechenden Schlüsseln einer Compose-Datei. Wenn Sie Ihren Stack bereits in einer Docker-Compose-Datei auf einem VPS verwalten, steht das Limit neben dem Dienst, für den es gilt, und wird zusammen mit ihm in git versioniert.
FreeBSD verwendet rctl. Dieses Subsystem müssen Sie aktivieren. Die Ressourcenabrechnung ist standardmäßig deaktiviert, weil sie bei jeder Zuweisung einen geringen Mehraufwand verursacht. Fügen Sie das Tuning-Parameter in /boot/loader.conf ein und starten Sie das System neu:
kern.racct.enable=1Legen Sie anschließend eine Regel fest und überwachen Sie sie:
sudo rctl -a jail:web:vmemoryuse:deny=1g
rctl -hu jail:webrctl -hu jail:web gibt die aktuelle Nutzung des Jails in lesbaren Einheiten aus. So sehen Sie, wie nahe die Nutzung am Limit liegt, bevor ein Fehler auftritt. Die Aktion deny lässt die Zuweisung innerhalb des Limits fehlschlagen. Dadurch sehen Sie den eigenen Zuweisungsfehler der Anwendung und keine Kill-Meldung auf dem Host.
Mit rctl -a hinzugefügte Regeln gehen beim nächsten Reboot verloren. Der FreeBSD-Dienst rctl lädt sie aus /etc/rctl.conf. Schreiben Sie die Regel daher in diese Datei und aktivieren Sie den Dienst:
sudo sysrc rctl_enable=YESIn diesem Punkt ist Docker deutlich bequemer. Ein Limit in einer Compose-Datei wird zusammen mit dem Dienst geprüft, den es begrenzt. Eine rctl-Regel steht dagegen als Zeile in einer separaten Datei und verweist auf ein Jail, das an anderer Stelle definiert ist.
Wenn die Antwort eine virtuelle Maschine ist: bhyve
Ein Jail verwendet den Kernel des Hosts. Daher sind bestimmte Funktionen grundsätzlich nicht verfügbar. Es kann keine andere Kernel-Version ausführen, kein Kernel-Modul laden und keine Linux-Binärdateien wie ein Linux-Container ausführen. FreeBSD verfügt mit dem linuxulator über eine Linux-Kompatibilitätsschicht. Diese implementiert jedoch nur einen Teil der Linux-Systemaufrufe und ist keine allgemeine Lösung für beliebige Linux-Images.
bhyve ist der Hypervisor von FreeBSD. Er ist das geeignete Werkzeug, wenn Sie eine echte Maschinengrenze benötigen: ein anderes Betriebssystem, einen anderen Kernel oder einen Mandanten, mit dem Sie den Kernel möglichst nicht gemeinsam nutzen möchten. Dafür benötigen Sie reservierten statt gemeinsam genutztem Arbeitsspeicher und müssen einen zweiten Kernel patchen. Diese Entscheidung entspricht der Wahl zwischen Containern und vollständigen virtuellen Maschinen unter Linux. Sie entscheidet auch darüber, ob Sie darunter einen VPS mit Unterstützung für verschachtelte Virtualisierung benötigen.
Das Ökosystem ist der ausschlaggebende Grund, warum die meisten Teams Docker verwenden
Bisher ging es um das Modell. Für die meisten Teams entscheidet jedoch die Größe des Umfelds, das jedes Modell mitbringt.
Docker bietet Docker Hub und GHCR, docker compose, Kubernetes, sobald ein einzelner Rechner nicht mehr ausreicht, CI-Runner mit bereits integrierter Container-Unterstützung und einen Quickstart mit einem einzigen Befehl in der README-Datei fast jedes Projekts. Jails bieten den FreeBSD-Ports-Tree, der umfangreich und sorgfältig gepflegt ist, sowie eine deutlich kleinere Auswahl an sofort ausführbaren Anwendungspaketen. Wenn ein Projekt nur ein Container-Image und nichts anderes veröffentlicht, müssen Sie für den FreeBSD-Weg die Dokumentation lesen und die einzelnen Komponenten selbst zusammenstellen.
Jails haben auf der anderen Seite dieses Kompromisses ihre Berechtigung. Sie eignen sich, wenn Sie bereits ZFS verwenden und Snapshots sowie Rollbacks eines vollständigen Dienstes benötigen, wenn Ihre Dienste nativ unter FreeBSD laufen, wenn Sie pro Mandant ein vollständiges Userland statt nur eines einzelnen Prozesses benötigen oder wenn Kernel, Paketfilter, Dateisystem und Dokumentation gemeinsam als ein System gepflegt werden sollen. Dieser letzte Punkt ist gemeint, wenn FreeBSD als kohärent bezeichnet wird. Der ausführlichere Vergleich von Linux und FreeBSD als Serverplattformen behandelt ihn ebenfalls. Dasselbe gilt für die Änderungen von FreeBSD 15 für den Servereinsatz.
Eine abschließende Einschätzung: Wenn Ihr Team Docker bereits beherrscht, sind die Kosten eines Wechsels real, und der Nutzen muss konkret sein. Wechseln Sie nicht wegen einer besseren Isolation. Die beiden Modelle sind in diesem Punkt ähnlich genug, dass Ihre Konfiguration wichtiger ist. Wechseln Sie, wenn Sie Rollbacks vollständiger Dienste auf Basis von ZFS benötigen oder bereits FreeBSD einsetzen.
FAQ
Kann ich Docker-Images auf FreeBSD ausführen?
Nicht Linux-Images und auch nicht auf einem unterstützten Weg. FreeBSD unterstützt OCI-Container: sudo pkg install -y podman-suite installiert Podman. Podman führt Container über ocijail aus, eine Laufzeitumgebung, die darunter echte Jails erstellt. Für die Überwachung der Container muss fdescfs auf /dev/fd eingehängt sein. Für das Container-NAT (Network Address Translation) wird pf benötigt. OCI-Images für FreeBSD funktionieren am besten. Linux-Images benötigen zusätzlich die Linux-Kompatibilitätsschicht. Im August 2026 wird der FreeBSD-Port von Podman weiterhin als experimentell beschrieben. Wenn Ihre Bereitstellung aus einem Stack von Linux-Images besteht, führen Sie ihn unter Linux aus. In der RHEL-Familie bedeutet das Docker auf Rocky Linux oder AlmaLinux zu installieren. Dort taucht Podman ein zweites Mal als Paket auf, das den Befehl docker bereits bereitstellt, bevor Sie etwas installiert haben.
Sind FreeBSD-Jails sicherer als Docker-Container?
Beide verwenden denselben Kernel des Hosts. Ein Kernel-Fehler stellt daher für beide ein Risiko dar. Für wirklich nicht vertrauenswürdigen Code würden Sie weder das eine noch das andere als Sicherheitsgrenze wählen. Der Unterschied liegt in der Ausgangskonfiguration. Ein Jail verweigert zunächst eine große Anzahl von Operationen. Sie aktivieren diese anschließend einzeln über Parameter. Ein Docker-Container startet als root in einer Gruppe von Namespaces, wobei einige Capabilities entfernt wurden. Eine zusätzliche Härtung müssen Sie ausdrücklich aktivieren. In der Praxis ist die Konfiguration wichtiger als das Modell: Ein Jail mit aktiviertem allow.mount und allow.raw_sockets ist nicht sicherer als ein sorgfältig konfigurierter Container.
Wie sichere ich ein Jail?
Erstellen Sie einen Snapshot des Datasets und übertragen Sie ihn. sudo zfs snapshot zroot/jails/containers/web@backup erstellt den Snapshot. Anschließend übertragen Sie ihn mit zfs send in einen anderen Pool oder in eine Datei, die Sie vom Host wegkopieren. Da ein Jail sein vollständiges Userland in einem Dataset speichert, enthält der Snapshot die installierten Pakete und die Daten zu einem einheitlichen Zeitpunkt. Er enthält außerdem jede Konfigurationsdatei, die Sie manuell bearbeitet haben. Das ist das Gegenteil der Docker-Praxis. Dort sichern Sie die benannten Volumes und die Compose-Datei und erstellen den restlichen Inhalt aus dem Image neu.
Benötige ich BastilleBSD, oder reicht das Basissystem aus?
Das Basissystem reicht aus und ist der bessere Ausgangspunkt. jail.conf, jls, jexec und service jail start decken das gesamte Modell ab. Sobald Sie diese Befehle kennen, können Sie jeden FreeBSD-Host untersuchen, ohne zuerst dessen spezifische Werkzeuge lernen zu müssen. Bastille ist eine darüberliegende Komfortschicht. Es richtet Releases ein, erstellt Thin Jails, wendet Templates an und schreibt pf-Redirect-Regeln für Sie. Lernen Sie zuerst die Befehle des Basissystems. Fügen Sie Bastille anschließend hinzu, wenn die Anzahl der Jails das manuelle Eingeben aufwendig macht.