Ferrocrate runs containers the way Docker does, from a single Rust binary.
Point your existing docker CLI, Dockerfiles, and Compose files at it and
they work unchanged; or use the native ferro-cli command, the desktop app,
or the fleet control plane. On Linux a container is a normal process the
kernel isolates, and that is where the speed comes from.
Status: alpha release. The feature matrix is the public source of truth for supported, experimental, and unsupported behavior. All CI and release jobs use self-hosted runners only.
Download a package from the latest release, then follow the platform guide. These are local, unsigned builds: not notarized, not code-signed, and the in-app updater is disabled until a signed release ships.
| Platform | Package | Download | Guide |
|---|---|---|---|
| macOS 13+ (Intel) | FerroCrate_Desktop_0.1.0_x64.dmg |
.dmg | Install on macOS |
| Linux (x86_64, glibc) | FerroCrate.Desktop_0.1.0_amd64.deb or .AppImage |
.deb | .AppImage | Install on Linux |
| Windows 10/11 (x64) | FerroCrate.Desktop_0.1.0_x64-setup.exe or .msi |
.exe | .msi | Install on Windows |
| Linux (aarch64, glibc) | FerroCrate.Desktop_0.1.0_arm64.deb or .AppImage |
.deb | .AppImage | Install on Linux |
Open the .dmg, drag FerroCrate Desktop to Applications. Gatekeeper
blocks an unsigned app on the first launch: right-click the app in
Applications and choose Open, then confirm. Later launches open normally.
Debian/Ubuntu: sudo apt install ./FerroCrate.Desktop_0.1.0_amd64.deb
Any distro (glibc-based): make the AppImage executable and run it —
chmod +x FerroCrate.Desktop_0.1.0_amd64.AppImage && ./FerroCrate.Desktop_0.1.0_amd64.AppImage
Run the installer. Since it isn't signed, SmartScreen will show "Windows protected your PC" — click More info, then Run anyway.
The desktop app shows Compose projects as workspaces, with per-service status,
ports, CPU and memory, and one-click logs, terminal and stop. Start it from a
checkout with scripts/dev-desktop.sh (add --web to open it in a browser).
Every command below was run as a normal user, without sudo, on the Linux
host that builds this repository. The native CLI needs no daemon: each command
does its own work and keeps images, containers and volumes under
~/.ferrocrate (/var/lib/ferrocrate when run as root; set FERROCRATE_HOME
to use another directory). If you know Docker, the commands and flags are the
same; only the binary name differs.
- A Linux host from the platform support table. macOS and Windows users get the desktop app, not the CLI.
- Rust through
rustup. The repository pins the toolchain inrust-toolchain.toml, sorustupinstalls the right version on first build. - For rootless use: unprivileged user namespaces enabled, entries for your
user in
/etc/subuidand/etc/subgid, and thenewuidmap,newgidmap,slirp4netnsandbwrapbinaries.bash scripts/verify-rootless.shtells you what is missing. - The
dockerCLI, only if you want step 6.
git clone https://github.com/dgdev25/ferrocrate.git
cd ferrocrate
cargo build --release -p ferro-cli
install -m 755 target/release/ferro-cli ~/.local/bin/ferro-cli # optional, puts it on PATHferro-cli run --rm alpine:3.20 echo helloThis pulls the image, verifies every layer digest, runs the command and removes the container. The first two output lines are the container id and the runtime details; your command's output follows.
mkdir hello && cd hello
cat > Dockerfile <<'EOF'
FROM alpine:3.20
COPY hello.sh /hello.sh
CMD ["/bin/sh", "/hello.sh"]
EOF
printf '#!/bin/sh\necho "hello from ferrocrate"\n' > hello.sh
ferro-cli build -t hello:1.0 .
ferro-cli images
ferro-cli run --rm hello:1.0build also accepts --build-arg, --secret, --cache-from and
--cache-to, as Docker does.
ferro-cli run -d --name web -p 8080:8080 -v webdata:/www busybox:1.36 \
sh -c 'echo hello > /www/index.html; exec httpd -f -v -p 8080 -h /www'
curl http://127.0.0.1:8080/ # hello
ferro-cli ps # running containers; -a includes stopped ones
ferro-cli logs --tail 5 web # -f follows
ferro-cli exec web ls /www # run a command inside; -it for a shell
ferro-cli stop web
ferro-cli start web
ferro-cli stop web
ferro-cli rm web
ferro-cli volume rm webdatacat > compose.yaml <<'EOF'
services:
app:
image: alpine:3.20
command: ["sh", "-c", "echo compose says hi; sleep 3600"]
EOF
ferro-cli compose up -d
ferro-cli compose ps
ferro-cli compose logs
ferro-cli compose downcompose also has stop, start, restart, pull, config and watch.
Start the daemon with the Docker-compatible API on, then point DOCKER_HOST
at its socket. The daemon shares the same state directory as the native CLI,
so images built one way are visible the other way.
# rootless
ferro-cli daemon --docker-compat --socket "$XDG_RUNTIME_DIR/ferrocrate.sock" &
export DOCKER_HOST="unix://$XDG_RUNTIME_DIR/ferrocrate.sock"
# or as root (default socket /var/run/ferrocrate.sock)
sudo ferro-cli daemon --docker-compat &
export DOCKER_HOST=unix:///var/run/ferrocrate.sock
docker version
docker build -t hello:1.0 .
docker run --rm hello:1.0
docker ps -aDocker's default BuildKit path works through this socket; see How it works for the limits.
kill %1 # stop the daemon from step 6 (as root: sudo pkill -x ferro-cli)
ferro-cli rmi hello:1.0
ferro-cli system prune # stopped containers, unused images, build cache
ferro-cli volume pruneOptional: ferro-cli dashboard --listen 127.0.0.1:43190 serves a local
browser dashboard for the life of the command and prints a one-time token URL.
Your command, from docker or the native CLI, reaches the daemon on a
Docker-compatible API socket (the same protocol Docker speaks, so existing
tools do not know the difference). The runtime unpacks the image layers,
isolates the process with Linux namespaces and cgroups (the kernel features
that give a process its own view of the filesystem, network, and resource
limits), wires its network, and starts it. There is no virtual machine on
Linux and no second daemon: one binary does the work.
Builds go through the same daemon. Docker's default BuildKit path is
supported through the authenticated Buildx docker driver; the classic build
path is kept and produces the same image digest. Arbitrary LLB and
gateway.v0 frontends are not supported.
All numbers below are medians from paired runs on the same host, with both engines unprivileged and the same image. Negative means Ferrocrate is faster. The benchmark method explains how release candidates collect and qualify fresh results.
Host: Intel i9-14900K, 32 threads, 61 GB RAM, Ubuntu 26.04, kernel 7.0.0-30,
Docker 29.7.2. alpine:latest, --network none, 10 iterations (5 for pull
and build).
| Operation | Ferrocrate | Docker | Difference |
|---|---|---|---|
| Start container (detached) | 0.008 s | 0.114 s | −93% |
Stop container (-t 1) |
0.032 s | 1.115 s | −97% |
| Exec a command | 0.016 s | 0.064 s | −75% |
| Read 1,000 log lines | 0.007 s | 0.016 s | −52% |
List containers (ps -a) |
0.007 s | 0.032 s | −76% |
| List images | 0.008 s | 0.114 s | −93% |
| Create a volume | 0.008 s | 0.016 s | −52% |
| Build, no cache (COPY-only Dockerfile) | 0.008 s | 0.264 s | −97% |
| Build, cached (COPY-only Dockerfile) | 0.007 s | 0.765 s | −99% |
| Run to exit (attached) | 0.364 s | 0.164 s | +122% (Docker faster) |
| Cold pull (baseline run only) | 1.474 s | 3.183 s | −54% |
These results describe that dated host and build, not the current release candidate. Functional coverage is separate from speed; use the feature matrix for the supported surface.
Four kinds of client, one daemon, three subsystems, one kernel:
- Clients: the native CLI (
ferro-cli), any Docker client over the compatible API, Compose (ferro-compose), and Kubernetes through the CRI (ferro-cri, the interface a kubelet uses to ask a runtime for pods). - Daemon: one binary that owns state and dispatches work.
- Container runtime (
ferro-core): creates and supervises containers, with PID-identity checks so only the caller that started a container can act on it. - Image store: OCI layers and the build cache.
- Networking (
ferro-net,ferro-netd): bridges, DNS, IPv6, WireGuard, iptables or nftables backends; eBPF port publishing is opt-in. - Kernel: namespaces, cgroups, seccomp, netfilter, eBPF. Ferrocrate adds no layer between the container and the kernel.
Around the engine: ferro-desktop and the Tauri app in apps/ferro-desktop-ui
(desktop on Linux, WSL2 on Windows, a QEMU/HVF Linux VM on macOS), ferro-mgr
(fleet control plane with a certificate-bound browser UI), ferro-web (the
shared browser transport), and ferro-mind (resource monitoring and anomaly
features for containers).
| Platform | Status |
|---|---|
| Ubuntu 26.04 / 24.04, Debian 12 / 13, Fedora 42, Alpine 3.22 (x86_64, rootful) | Supported; dated rows in the feature matrix |
| Ubuntu 24.04 on Oracle A1 (aarch64, kernel 6.17) | Supported; dated row in the feature matrix |
| Rocky 9 (kernel 5.14), Ubuntu 20.04 HWE (kernel 5.15) | Qualified with opt-in legacy-peercred; the default pidfd authentication fails closed on these kernels |
| Rootless mode | Qualified on the host rows in the feature matrix; a missing SO_PEERPIDFD fails closed unless legacy peercred is enabled |
| Windows 11 | Unsigned alpha desktop package; WSL2 runtime qualification is in progress |
| macOS Tahoe | Unsigned Intel alpha desktop package; Linux VM runtime qualification is in progress |
Images are built and run only for the host's architecture. There is no
emulation of foreign architectures, no --platform builds, and no
multi-architecture manifests.
The authoritative support contract is
docs/FEATURE-MATRIX.md. It states where a feature
is experimental or unsupported.
- Fleet UI:
ferro-mgr fleet-uimanages enrolled hosts over an operator-authenticated mTLS admin endpoint, with read-onlyviewsessions and auditedoperateactions. Local demo:scripts/fleet-demo.sh up. - Dashboard: the local browser dashboard uses a one-time bearer token and restricts Host and Origin values.
- LAN image mirror (experimental, opt-in): announces images by mDNS and serves digest-verified, read-only pulls to peers on private IPv4, falling back to the registry.
- Packaging: Linux deb and AppImage, macOS DMG, Windows MSI and NSIS. The macOS and Windows artifacts are not code-signed.
- Security and hosts:
scripts/verify-apparmor-rootless-host.shqualifies the packaged Ubuntu AppArmor profile on a disposable host; seeSECURITY.md.
cargo test --workspace # full suite
cargo test -p ferro-core --lib # runtime core
bash scripts/docker-client-conformance.sh # 85-scenario docker CLI gateGitHub Actions runs the build, unit, frontend, and warning gates on
self-hosted Linux, macOS, and Windows runners; scheduled canaries build the
platform bundles. See CONTRIBUTING.md and the
docs/RELEASE.md release guide.