
JIT-basierter Userspace-Linux-Kernel, der Container nativ auf Apple Silicon macOS ohne VM ausführt. Drop-in Docker Engine API-Ersatz mit Container-Isolation, Overlay-Images und Portveröffentlichung.
Linux-Container auf macOS ausführen – ohne VM.
dd führt Linux-Container nativ auf Apple-Silicon macOS ohne virtuelle Maschine aus. Es gibt keinen
Linux-Kernel und keinen Hypervisor darunter: Ein JIT übersetzt den Code des Containers und bedient seine
Linux-Systemaufrufe im Userspace (die gVisor-/PRoot-Linie). Der JIT ist der Linux-Kernel des Gasts –
Namespaces, Cgroups, Overlay-Image-Layer und Netzwerk werden als Userspace-Zustand verwaltet. Er spricht
die Docker Engine API, sodass die normale docker-CLI ihn steuert.
Die Berechnung des Containers läuft als native Apple-Silicon-Instruktionen; nur seine Systemaufrufe werden interpretiert. Keine VM zum Booten, kein Daemon-in-einer-VM, keine Virtualisierungskosten.
Website & Dokumentation: https://ricccrd.github.io/dd/
make jit # build.rs kompiliert + codesignt die JITs
DD_IMAGES=/path/to/images cargo run -p dd-daemon # starte den Daemon
export DOCKER_HOST=unix://$PWD/dd.sock
docker run -p 8080:80 -m 256m alpine sh -c 'echo hi from $(hostname)'
DOCKER_HOST auf seinen Socket und deine
vorhandenen docker run / ps / images / build-Befehle funktionieren unverändert.jit86), der x86 dekodiert, seine Flags synthetisiert und SSE/x87 auf NEON herunterbricht (glibc-Binaries laufen);
und macOS arm64-Gäste (ddcli mac) – in keinem davon eine VM..wh.-Whiteout, gemergte getdents),
ein TOCTOU-freies Path-Jail-VFS, PID-/UTS-/USER-Namespaces, ein privates Loopback-Netns mit -p-Port-
Veröffentlichung und Cgroup-Speicher- + PIDs-Begrenzungen (OOM an der Grenze).dd-CLI installieren einen
benutzerbezogenen Hintergrund-Daemon und einen docker context – alles unter $HOME, niemals sudo.Jede andere Methode, Linux-Container auf einem Mac auszuführen – Docker Desktop, Colima, Rancher, OrbStack – bootet eine Linux-VM unter einem Hypervisor und betreibt den Daemon innerhalb dieser VM. Diese VM ist eine Steuer, die du den ganzen Tag bezahlst. dd entfernt sie: Ein Container ist ein normaler macOS-Prozess, dessen Systemaufrufe zufällig von einem Userspace-Linux-Kernel bedient werden.
| dd – Userspace-Kernel (JIT) | VM-basiertes Docker (Desktop / Colima / …) | |
|---|---|---|
| Zugrundeliegendes Modell | Ein JIT bedient Linux-Systemaufrufe im Userspace (gVisor-Linie) | Ein vollständiger Linux-Kernel in einer Hypervisor-VM |
| Resident RAM im Leerlauf | Kein – pro Container, beim Beenden freigegeben | Gigabytes für die VM reserviert, immer aktiv |
| Startzeit | Prozess starten – keine VM zum Booten | Erst eine Linux-VM + den Daemon in der VM booten |
| Bind-Mount / Datei-I/O | Direktes Host-Dateisystem durch ein Path-Jail | virtiofs/gRPC-FUSE-Brücke über die VM-Grenze |
| Port-Veröffentlichung | Direkt zu Host-Sockets | Über die NAT-/Forwarding-Schicht der VM |
| Akku-/Hintergrundkosten | Nichts läuft, wenn kein Container aktiv ist | Eine VM, die im Leerlauf läuft und den Akku leert |
| Größe zum Ausliefern & Patchen | Kein Linux-Kernel – nichts zu CVE-verfolgen | Liefert, patcht und verfolgt einen ganzen Linux-Kernel |
| Beobachtbarkeit | Ein normaler macOS-Prozess – sample, debugge, Aktivitätsüberwachung | Eine undurchsichtige VM; die Arbeitslast ist für Host-Tools unsichtbar |
Der Gewinn ist strukturell: Die Berechnung des Gasts läuft als native Apple-Silicon-Instruktionen (keine
Hardwarevirtualisierungsschicht im heißen Pfad), und der berüchtigte Docker-Desktop-Dateifreigabe-Engpass –
die virtiofs/FUSE-Brücke zwischen macOS und der VM – existiert einfach nicht, weil das VFS von dd das Host-Dateisystem
hinter einem Path-Jail ist.
Ehrlicher Kompromiss: Ein Userspace-Kernel ist nur so vollständig wie die Systemaufrufe, die er implementiert, und heute läuft der Gast standardmäßig in einem Prozess – schnell und die richtige Wahl für Code, dem du vertraust (deine Entwicklungs- umgebung, CI, deine eigenen Tools). Für nicht vertrauenswürdigen Code gibt es jetzt eine optionale Sentry-Aufteilung (
DDJIT_UNTRUSTED): Der Gast läuft in einer Deny-Default-Seatbelt-Sandbox ohne Host-FS-/Netzberechtigung, während ein vertrauenswürdiger Sentry-Prozess die echten Ressourcen besitzt und Systemaufrufe über einen Shared-Memory- Ring bedient – die gVisor-Form. Es ist früh (die Kern-Dateisystemaufrufe – read/write/open/close/lseek – werden heute weitergeleitet; Sockets/exec/fork kommen), daher legt eine VM für vollständig feindlichen Code immer noch eine schmalere Oberfläche frei.
Das gleiche statische Linux-Binary, zweimal ausgeführt auf einem Apple M5 Pro (macOS 26.3): innerhalb der Linux-VM
(wie VM-basiertes Docker Container ausführt) vs. durch dd's JIT auf dem Host ohne VM. Median von 7
(make bench). Niedrigere Zeit ist besser; „dd vs VM“ > 1× bedeutet, dd ist schneller. Die dd-Spur bezahlt sogar eine kleine
Cross-Prozess-Brückensteuer, die die echte Anwendung nicht hat – also sind diese konservativ.
x86-64-Container – dd vs. VM-Emulation (qemu-user; x86 auf Apple Silicon ausführen bedeutet Übersetzung in beiden Fällen). dd's JIT schlägt qemu in 9 von 10 Workloads, dramatisch bei Fließkomma:
| Workload | VM (qemu) | dd (keine VM) | dd vs VM |
|---|---|---|---|
| float n-body | 5,39 s | 0,23 s | 24× schneller |
| Mandelbrot | 7,81 s | 0,83 s | 9,4× schneller |
| Matmul | 8,21 s | 1,37 s | 6,0× schneller |
| SQLite (600k Zeilen) | 2,99 s | 1,01 s | 3,0× schneller |
| Qsort | 3,91 s | 1,68 s | 2,3× schneller |
| Memcpy | 2,40 s | 1,10 s | 2,2× schneller |
| Text-Scan (wc/grep) | 1,42 s | 1,11 s | 1,3× schneller |
| int sieve | 1,31 s | 1,04 s | 1,25× schneller |
| SHA-256 | 2,72 s | 2,44 s | 1,1× schneller |
| Base64 | 4,28 s | 5,39 s | 0,79× (1,26× langsamer) |
aarch64-Container – dd vs. native VM (die VM läuft arm64 mit voller nativer Geschwindigkeit – die härteste Hürde):