
JIT 기반 사용자 공간 리눅스 커널로, Apple Silicon macOS에서 VM 없이 네이티브로 컨테이너를 실행합니다. 컨테이너 격리, 오버레이 이미지 및 포트 퍼블리싱을 갖춘 Drop-in Docker Engine API 대체제입니다.
macOS에서 Linux 컨테이너 실행 — VM 없이.
dd는 가상 머신 없이 Apple Silicon macOS에서 Linux 컨테이너를 기본적으로 실행합니다. 밑에는 Linux 커널과 하이퍼바이저가 없습니다. JIT가 컨테이너의 코드를 변환하고 Linux 시스템 콜을 사용자 공간에서 처리합니다 (gVisor / PRoot 계열). JIT 자체가 게스트의 Linux 커널입니다 — 네임스페이스, cgroups, 오버레이 이미지 레이어 및 네트워킹이 사용자 공간 상태로 유지됩니다. Docker Engine API를 사용하므로 일반 docker CLI로 구동할 수 있습니다.
컨테이너의 연산은 기본 Apple Silicon 명령어로 실행되며, 시스템 콜만 해석됩니다. 부팅할 VM, VM 내 데몬, 가상화 비용이 없습니다.
웹사이트 및 문서: https://ricccrd.github.io/dd/
make jit # build.rs가 JIT를 컴파일하고 코드사인
DD_IMAGES=/path/to/images cargo run -p dd-daemon # 데몬 시작
export DOCKER_HOST=unix://$PWD/dd.sock
docker run -p 8080:80 -m 256m alpine sh -c 'echo hi from $(hostname)'
DOCKER_HOST를 해당 소켓으로 지정하면 기존의 docker run / ps / images / build 명령어가 변경 없이 작동합니다.jit86가 x86을 디코딩하고 플래그를 합성하며 SSE/x87을 NEON으로 변환 — glibc 바이너리 실행 가능), macOS arm64 게스트 (ddcli mac) — 모두 VM이 필요하지 않습니다..wh. whiteout, 병합된 getdents), TOCTOU 없는 경로 감옥 VFS, PID / UTS / USER 네임스페이스, -p 포트 게시 기능을 갖춘 개인 루프백 netns, cgroups 메모리 + pid 제한 (제한에서 OOM).dd CLI가 사용자별 백그라운드 데몬과 docker context를 설치합니다. 모든 것은 $HOME 아래에 있으며, sudo는 필요하지 않습니다.Mac에서 Linux 컨테이너를 실행하는 다른 모든 방법 — Docker Desktop, Colima, Rancher, OrbStack — 은 하이퍼바이저 아래에서 Linux VM을 부팅하고 데몬을 그 안에서 실행합니다. 그 VM은 하루 종일 지불하는 세금입니다. dd는 이를 제거합니다: 컨테이너는 시스템 콜이 우연히 사용자 공간 Linux 커널에 의해 처리되는 일반 macOS 프로세스입니다.
구조적으로 이득이 있습니다: 게스트의 연산은 네이티브 Apple Silicon 명령어로 실행되며 (핫 경로에 하드웨어 가상화 계층 없음), 악명 높은 Docker-Desktop 파일 공유 병목 현상 — macOS와 VM 사이의 virtiofs/FUSE 브리지 — 은 dd의 VFS가 경로 감옥 뒤의 호스트 파일 시스템이기 때문에 존재하지 않습니다.
솔직한 트레이드오프: 사용자 공간 커널은 구현된 시스템 콜만큼만 완전하며, 오늘날 기본적으로 게스트는 단일 프로세스로 실행됩니다 — 빠르며, 신뢰할 수 있는 코드(개발 환경, CI, 자신의 도구)에 적합합니다. 신뢰할 수 없는 코드를 위해 이제 선택적 센트리 분할(
DDJIT_UNTRUSTED)이 있습니다: 게스트는 호스트 fs/네트워크 권한이 없는 거부-기본 Seatbelt 샌드박스에서 실행되는 반면, 신뢰할 수 있는 센트리 프로세스가 실제 리소스를 소유하고 공유 메모리 링을 통해 시스템 콜을 제공합니다 — gVisor 구조입니다. 아직 초기 단계이며(핵심 파일 시스템 콜 — read/write/open/close/lseek — 만 오늘날 전달됨; 소켓/exec/fork는 준비 중), 완전히 적대적인 코드의 경우 VM이 여전히 더 좁은 표면을 노출합니다.
동일한 정적 Linux 바이너리를 Apple M5 Pro (macOS 26.3)에서 두 가지 방식으로 실행: Linux VM 내부 (VM 기반 Docker가 컨테이너를 실행하는 방식) vs. dd의 JIT를 통해 호스트에서 VM 없음. 7회 중앙값 (make bench). 시간이 짧을수록 좋음; "dd 대 VM" > 1×는 dd가 더 빠름을 의미합니다. dd 레인은 실제 앱이 지불하지 않는 작은 교차 프로세스 브리지 비용도 부담하므로 이는 보수적입니다.
x86-64 컨테이너 — dd 대 VM 에뮬레이션 (qemu-user; Apple Silicon에서 x86 실행은 어느 쪽이든 변환을 의미). dd의 JIT는 10개 워크로드 중 9개에서 qemu를 이기며, 특히 부동 소수점에서 크게 앞섭니다:
aarch64 컨테이너 — dd 대 네이티브 VM (VM은 arm64를 완전 네이티브 속도로 실행 — 가장 어려운 기준):
dd는 arm64 연산을 네이티브 속도로 실행합니다 — int sieve + mandelbrot에서 앞서고, SHA-256, matmul, memcpy, n-body, base64에서 동등합니다. 나머지 차이는 간접 분기 / 시스템 콜 중심 작업입니다 — qsort (~1.3배), 텍스트 스캔 (~1.35배), SQLite (~1.5배) — 최신 패스(§B-off + 도난 x16/x17으로 SQLite가 ~1.9배에서 ~1.5배로 좁혀짐)로 크게 좁혀졌습니다. 나머지(VDBE 디스패치)를 닫는 것이 활성 개척지입니다. docs/design/arm-sqlite-parity.md를 참조하세요. (모든 워크로드는 0.45초 이상 실행되도록 크기가 조정되어, 실행당 작은 브리지 비용은 여기서 무시할 수 있습니다.)
이것들은 연산 마이크로벤치마크입니다 — dd의 구조적 이점(부팅할 VM 없음, 상주 RAM 없음, 직접 호스트 파일 시스템 I/O)조차 포착하지 않습니다. 모든 수치는 측정된 7회 중앙값입니다. 재현: make bench.
목표는 모든 벤치마크에서 VM을 이기는 것입니다. dd는 이미 위의 모든 x86-64 워크로드에서 이기고 네이티브 arm64와 일치하거나 능가합니다; 여전히 뒤처진 곳 — 시스템 콜/할당 중심의 arm64 SQLite 및 x86 변환기에서 더 많은 성능을 끌어내는 것 — 이 바로 최적화 개척지입니다 (티어-2 트레이스 최적화 프로그램 및 jit86 성능 작업). 모든 곳에서 동등 이상이 기준입니다.
dd는 사용자 공간에서의 커널이 되어 Linux 컨테이너를 실행합니다. JIT가 게스트의 기계어 코드를 변환하고 모든 시스템 콜 명령어를 가로챕니다; 트랩 핸들러 — dd-jit/src/runtime/os/linux/의 service() — 는 macOS 호스트에 대해 구현된 Linux 시스템 콜 ABI입니다.
ld.so를 통해) 및 초기 스택 구성.# 1. 데몬 시작, docker를 그것에 연결
make jit
DD_IMAGES=/path/to/images cargo run -p dd-daemon
export DOCKER_HOST=unix://$PWD/dd.sock
# 2. 그냥 Docker입니다
docker run -p 8080:80 -m 256m alpine sh -c 'echo hi from $(hostname)'
docker ps
docker images
docker run --rm -it ubuntu bash
# 3. 또는 설치된 데스크톱 앱을 통해 (사용자별, 루트 불필요)
dd install # LaunchAgent + docker context
dd app # GUI 열기
docker --context dd run alpine echo hi
dd는 Apple Silicon macOS (arm64, macOS 12+)를 대상으로 합니다. JIT에는 Xcode Command Line Tools (clang + codesign)가 필요합니다.
릴리스 페이지에서 최신 .dmg를 받아 열고 dd를 Applications로 드래그하세요. 그런 다음 터미널에서:
dd install # ~/.dd 트리 + 사용자별 LaunchAgent + `docker context create dd`
dd app # GUI 열기
dd doctor # 소켓 / 에이전트 / 컨텍스트 / 앱 격리 검사
Gatekeeper: DMG는 서명되지 않았습니다(애드혹). 처음 실행 시 앱을 마우스 오른쪽 버튼으로 클릭 → 열기, 또는
xattr -dr com.apple.quarantine /Applications/dd-app.app실행 (dd doctor가 이를 감지하고 수정 방법을 출력합니다).
xcode-select --install # clang + codesign
# Rust (stable) 및 Nix (GTK4 개발 셸용) 설치
git clone https://github.com/ricccrd/dd && cd dd
make app # 빌드 + 조립 및 애드혹 서명 target/dd-app.app
make dmg # -> target/dist/dd-<ver>-<arch>.dmg
make install # /Applications에 복사하고 `dd install` 실행
make app/dmg는 Nix 개발 셸(nix/flake.nix) 내에서 번들을 실행하며, GTK4 + dylibbundler / create-dmg를 제공합니다. 번들은 GTK dylib 그래프를 Contents/Frameworks로 재배치하고, GTK 런타임 데이터를 스테이징하며, 내부→외부로 애드혹 서명합니다.
Cargo 작업 공간입니다.
dd-jit/ — JIT 런타임 (C, src/runtime/ 아래) 및 Rust 바인딩. build.rs가 게스트 아키텍처별로 하나의 JIT 바이너리 (aarch64, x86_64)를 컴파일하고 코드사인합니다; src/lib.rs는 Guest + 타입화된 SpawnConfig 실행 계약을 노출합니다. aarch64 게스트는 완전히 분해되어 있습니다 (jit/ 엔진 + os/linux/ 개성 + frontend/aarch64/); x86-64 게스트 (jit86)는 os/linux/ 계층을 공유합니다.dd-daemon/ — Docker Engine API 데몬. 각 이미지의 게스트 아키텍처를 ELF에서 감지하고, 일치하는 JIT를 선택하여 SpawnConfig를 통해 실행합니다.데몬은 ~/.dd/run/docker.sock에서 수신합니다; GUI와 docker --context dd 모두 이를 사용합니다. 상태는 ~/.dd/state.json에 유지됩니다.
make test # 엔진 × 케이스 매트릭스, 그룹 보고서
make test ENGINE=x86_64 # 하나의 엔진
make test FILTER=container # 이름과 일치하는 하나의 그룹 / 케이스
cargo run -p dd-tests -- --list # 그룹 + 케이스 나열
make test-ci # cargo-test 경로 (CI)
케이스는 dd-tests/src/cases/에서 선언됩니다. 케이스는 게스트 프로그램 + 어설션입니다; aarch64 게스트는 즉시 컴파일 (gcc -static-pie)되고 네이티브 오라클과 비교됩니다. x86-64 게스트는 미리 빌드된 픽스처에서 가져옵니다. 각 케이스는 게스트가 있는 모든 엔진에서 실행됩니다.
clang + codesign (Xcode CLT)가 필요합니다.-p), 개인 루프백 netns, cgroup 메모리+pid 제한, UTS/PID/USER 네임스페이스.docs/를 참조하세요.Richard Hutta — [email protected]
MIT.
| dd — 사용자 공간 커널 (JIT) | VM 기반 Docker (Desktop / Colima / …) |
|---|
| 기본 모델 | JIT가 사용자 공간에서 Linux 시스템 콜을 처리 (gVisor 계열) | 하이퍼바이저 VM 내부의 완전한 Linux 커널 |
| 유휴 시 상주 RAM | 없음 — 컨테이너별로, 종료 시 해제 | VM용으로 예약된 기가바이트, 항상 켜져 있음 |
| 시작 | 프로세스 생성 — 부팅할 VM 없음 | Linux VM + VM 내 데몬을 먼저 부팅 |
| 바인드 마운트 / 파일 I/O | 직접 호스트 파일 시스템 (경로 감옥을 통해) | VM 경계를 넘는 virtiofs/gRPC-FUSE 브리지 |
| 포트 게시 | 호스트 소켓에 직접 연결 | VM의 NAT/포워딩 계층을 통해 |
| 배터리 / 백그라운드 비용 | 컨테이너가 없으면 아무것도 실행되지 않음 | 유휴 VM이 배터리 소모 |
| 배포 및 패치 공간 | Linux 커널 없음 — CVE 추적 불필요 | 전체 Linux 커널을 배포, 패치 및 추적 |
| 관찰 가능성 | 일반 macOS 프로세스 — sample, debug, Activity Monitor | 불투명한 VM; 호스트 도구에 워크로드가 보이지 않음 |
| 워크로드 | VM (qemu) | dd (VM 없음) | dd 대 VM |
|---|
| float n-body | 5.39초 | 0.23초 | 24배 빠름 |
| mandelbrot | 7.81초 | 0.83초 | 9.4배 빠름 |
| matmul | 8.21초 | 1.37초 | 6.0배 빠름 |
| SQLite (60만 행) | 2.99초 | 1.01초 | 3.0배 빠름 |
| qsort | 3.91초 | 1.68초 | 2.3배 빠름 |
| memcpy | 2.40초 | 1.10초 | 2.2배 빠름 |
| 텍스트 스캔 (wc/grep) | 1.42초 | 1.11초 | 1.3배 빠름 |
| int sieve | 1.31초 | 1.04초 | 1.25배 빠름 |
| SHA-256 | 2.72초 | 2.44초 | 1.1배 빠름 |
| base64 | 4.28초 | 5.39초 | 0.79배 (1.26배 느림) |
| 워크로드 | VM (네이티브) | dd (VM 없음) | dd 대 VM |
|---|
| int sieve | 0.75초 | 0.48초 | 1.58배 빠름 |
| mandelbrot | 0.79초 | 0.77초 | 1.03배 빠름 |
| matmul | 0.66초 | 0.66초 | ~동등 |
| memcpy | 0.55초 | 0.56초 | ~동등 |
| base64 | 0.68초 | 0.68초 | ~동등 |
| float n-body | 0.17초 | 0.17초 | ~동등 |
| SHA-256 | 0.80초 | 0.82초 | ~동등 |
| qsort | 0.83초 | 1.10초 | 1.33배 느림 |
| 텍스트 스캔 (wc/grep) | 0.51초 | 0.68초 | 1.35배 느림 |
| SQLite (60만 행) | 0.36초 | 0.62초 | 1.71배 느림 |
dd-tests/ — 선언적 테스트 하네스; 케이스가 모든 엔진에서 그룹 보고서와 함께 실행됩니다.dd-client/ — 데몬의 Unix 소켓을 통한 작은 타입화된 Docker-Engine-API 클라이언트 (와이어 형식의 단일 진실 공급원, GUI와 CLI에서 공유).dd-gui/ (바이너리 dd-app) — GTK4 데스크톱 UI. macOS에서만 Nix 개발 셸을 통해 빌드됩니다.dd-cli/ (바이너리 dd) — 설치/제어 인터페이스, 모두 루트 없이.