Incus excels at running system containers and VMs, but most tooling today assumes
OCI engines. incus-compose bridges that gap efficiently.
Incus is client/server. The daemon is Linux-only, but the incus client (and
incus-compose) is a cross-platform Go binary. From a Windows or macOS desktop
you connect to a remote Linux host over HTTPS and manage OCI app containers,
LXC system containers, and full VMs - all without Docker Desktop, WSL, or a
local Linux VM.
Docker Desktop cannot do this: on Windows and macOS it runs a hidden Linux VM to host the engine. With Incus the workload lives on real Linux infrastructure and your laptop is just a thin client.
See Installing on Windows for the client setup.
Running OCI engines inside Incus containers is a common pattern, but it's wasteful:
┌─────────────────────────────┐
│ Incus Container │
│ ┌──────────────────────┐ │
│ │ OCI Engine Daemon │ │
│ │ ┌────────────────┐ │ │
│ │ │ Your App │ │ │
│ │ └────────────────┘ │ │
│ └──────────────────────┘ │
└─────────────────────────────┘
Problems with this approach:
Run OCI images directly on Incus with incus-compose:
┌─────────────────────────────┐
│ Incus │
│ ┌────────────────┐ │
│ │ Your App │ │
│ └────────────────┘ │
└─────────────────────────────┘
Benefits:
| Feature | OCI Engines | Incus |
|---|---|---|
| Container type | Application (PID 1 = app) | System (full init) |
| Isolation | Namespaces only | LXC namespaces + cgroups |
| Security | Varying models | VM-like isolation |
| Networking | Port mapping via iptables | Real IPs and port proxies |
| Storage | Overlay filesystem | ZFS/Btrfs with instant snapshots |
| Image caching | Per-engine cache | Global blob cache, per-project alias |
Choose Incus when:
Stick with OCI engines when: