Pantavisor vs Docker: Why Docker Isn't Enough for Embedded Firmware
The Short Answer
Docker is great. Docker on embedded firmware is a poor fit.
Docker was designed for cloud and server workloads: ephemeral app containers, large hosts, network-attached storage, and an always-running dockerd daemon. Firmware on a 64β512 MB ARM device with eMMC, intermittent connectivity, and the requirement to never brick has different constraints. Pantavisor is built for those constraints from the ground up using LXC system containers.
Pantavisor still consumes Docker images β you don’t lose your registry investment β but the runtime, update model, and lifecycle are firmware-grade.
At a Glance
| Aspect | Docker | Pantavisor |
|---|---|---|
| Runtime | dockerd daemon + containerd |
LXC, no daemon |
| Footprint | ~50β100 MB just for the engine | ~1 MB Pantavisor + LXC |
| Container model | Single-process app containers | System containers (init + services + fs) |
| Kernel/BSP | Lives on the host, not Docker’s concern | A container in the same state |
| Update unit | Docker image layers | Content-addressed state objects |
| Atomic system update | β Per-container only | β Whole state revision |
| Automatic rollback on failure | β DIY | β
Built-in (boot + status_goal) |
| Signed system state | β οΈ Image signing only | β PVS over state JSON |
| Offline / air-gapped use | β οΈ Possible but awkward | β Native (local clone, USB push, mirrored Pantahub) |
| Storage backend | overlayfs required | overlayfs / squashfs / dm-verity / raw block |
| Boot dependency | Boots after host OS, host services | Pantavisor is PID 1 |
Why Docker Hurts on Embedded
1. The Daemon Tax
dockerd is a long-running root daemon. It eats RAM at idle, owns its own image cache, and is a single point of failure for every container on the box. On a server you don’t notice; on a 256 MB device you do. Pantavisor has no daemon β pantavisor is PID 1, and each LXC container is a normal supervised process tree.
2. Kernel and BSP Are Outside the Picture
Docker treats the kernel as a fixed property of the host. To change kernel, drivers, or device tree you need a separate update mechanism (Mender, RAUC, A/B partitions, custom scripts). With Pantavisor, the BSP is just another container in the state JSON β kernel updates are the same operation as app updates.
3. No Atomic System Update
Updating multiple Docker containers at once is not atomic. If you update three containers and the second fails, you’re in a half-updated state. Pantavisor switches the entire system state atomically β every container in the new revision is in place, or none of them are.
4. Rollback Is Yours to Build
Docker has no concept of “the previous good system state.” When an update breaks the device, you implement rollback yourself. Pantavisor monitors each container against its declared status_goal; if any container fails to reach it, the device automatically reverts to the last good state revision β no host-side scripts required.
5. Storage Assumptions Don’t Hold
Docker expects overlayfs and ample writable space for layer caches. Industrial flash often is read-mostly, dm-verity protected, or organized as squashfs for size. Pantavisor’s volume model is flexible: containers can mount squashfs root volumes, dm-verity-checked overlays, or persistent permanent volumes β whatever the device’s storage strategy demands.
6. Offline and Air-Gapped Are Second-Class
Pulling Docker images on flaky cellular or in air-gapped networks is painful. Pantavisor’s content-addressed object store ships only changed hashes, supports local mirrors of Pantahub, USB-stick deployment, and full offline operation as first-class workflows.
What Docker Still Does Well
- Developer ergonomics β
docker runis unbeatable for local iteration. - Image format and registries β the OCI ecosystem is huge.
- Cloud-native tooling β Kubernetes, CI runners, sidecars, etc.
Pantavisor doesn’t fight any of that. It treats Docker as an input format:
# Pull any Docker / OCI image and turn it into a Pantavisor container
pvr app add myapp --from=docker://nginx:latest
# Or in a Yocto recipe:
PVR_DOCKER_REF = "asac/alpine-dbus:latest"
inherit pvrexportYour existing Dockerfiles, registries, and image build pipelines keep producing artifacts. Pantavisor packages them into LXC system containers and ships them as part of a signed, atomic state.
When Docker Alone Is Fine
- Linux device with plenty of RAM/storage and a stable host OS you don’t update often.
- Apps are stateless services and rollback is handled at the orchestrator level (k3s, Nomad).
- You don’t need to update the kernel, drivers, or boot chain through the same pipeline.
- Connectivity is reliable.
When You Want Pantavisor Instead
- Real embedded constraints (low RAM, eMMC, possibly read-only rootfs).
- The kernel/BSP must be updateable through the same OTA channel as apps.
- Failed updates must never brick β automatic rollback is non-negotiable.
- You need signed, auditable system states for compliance.
- Devices are deployed in the field with intermittent or air-gapped connectivity.
- You want one update mechanism for the whole system, not five glued together.
Architectural Summary
Docker on embedded: Pantavisor:
βββββββββββββββββββββ ββββββββββββββββββββββββββ
β Host OS (build it β β Bootloader β
β yourself, OTA β ββββββββββββββββββββββββββ€
β it yourself) β β Pantavisor (PID 1) β
βββββββββββββββββββββ€ β β’ mounts /trails/N/ β
β dockerd daemon β β β’ starts LXCs β
βββββββββββββββββββββ€ β β’ watches status_goalβ
β App container β β β’ rolls back on fail β
β App container β ββββββββββββββββββββββββββ€
β App container β β bsp/ os/ app/ ... β
βββββββββββββββββββββ β (each = LXC container)β
ββββββββββββββββββββββββββKey Takeaway
Docker ships apps to servers. Pantavisor ships firmware to devices.
Use Docker for what it’s great at β building images and running cloud workloads. Use Pantavisor when the target is a constrained, long-lived, possibly disconnected device that must update its kernel, services, and apps as one signed unit and never brick.
Next Steps
- Composable Firmware β End-to-end build β flash β maintain
- Pantavisor vs Balena β How Pantavisor compares to the closest Docker-on-embedded competitor
- Pantavisor vs Yocto β Recommended way to build a Pantavisor-enabled image
- PVR Docker conversion β Use Docker images as container sources