Appears to be a CNCF sandbox project started by Red Hat.
Written in rust
Fundamentally,
bootcreuses the OCI image format as a way to transport serialized filesystem trees with included metadata such as aversionlabel, etc.
How does bootc differ from Docker?
Same format, completely different purpose
bootc uses the exact same OCI/Docker image format and tooling (Dockerfiles, podman build, registries, layers, etc.), but instead of packaging an application to run inside a container, you’re packaging a bootable operating system — including the Linux kernel itself (in /usr/lib/modules).
Key differences:
1. What runs at boot Docker runs your process in an isolated namespace with a container runtime as the outer wrapper. With bootc, once deployed to a machine, there is no outer container runtime — systemd is pid 1 directly, just like a normal Linux install. No namespace isolation, no cgroup magic from a runtime daemon.
2. The image includes a kernel A bootc image ships /usr/lib/modules/$kver/vmlinuz. Docker images never have a kernel — they share the host’s. When bootc installs to a machine, that kernel actually boots the hardware.
3. Updates are transactional OS updates, not container restarts bootc uses ostree under the hood to do atomic, transactional, in-place OS upgrades. You bootc upgrade, it fetches the new image, and on next reboot you’re running the updated OS. Rollback is also supported. This is the Fedora Silverblue / CoreOS model generalized.
4. Filesystem layout is different
/usris read-only at runtime (immutable)/etcis machine-local persistent state (with 3-way merge on updates)/varis where mutable runtime data lives- Docker containers have no such constraint — the whole FS is writable (via overlay)
5. Docker metadata is largely ignored ENTRYPOINT, CMD, ENV, EXPOSE, USER, HEALTHCHECK — all ignored by bootc at deploy time. The boot process is driven by the bootloader → kernel → initramfs → systemd, not by container metadata.
TL;DR: bootc lets you use the familiar Docker/OCI workflow (Dockerfile, podman build, push to registry) to build and distribute entire operating systems, not just applications. The image format is the same; the runtime model is completely different.
The bootc image is the OS
From the docs fetched earlier:
“At runtime on a target system, the base userspace is not itself running in a container by default. systemd acts as pid1 as usual — there’s no ‘outer’ process.”
What happens at boot:
- Bootloader → kernel (from inside the image,
/usr/lib/modules/$kver/vmlinuz) - initramfs does an ostree
chroot-equivalent into the deployment root - systemd starts as pid1 directly from the image filesystem
There is no host OS underneath. The image is the host. The container format is just the transport mechanism — once installed, the system boots and runs exactly like a conventional Linux install.
The only wrinkle is the physical root vs. logical root distinction: the raw disk’s root is mounted at /sysroot, while the booted OS lives under /sysroot/ostree/deploy/.../. This is an ostree implementation detail, not a second OS — it’s how ostree maintains A/B deployments on a single partition.
how do you use an existing distro if the directory layout is different?
This is a really good question and the honest answer is: it’s complicated, and non-Fedora/RHEL distros are a work in progress.
The core problem
bootc’s requirements push against traditional distro filesystem conventions in three specific ways:
1. Directory layout expectations
bootc/ostree expects the “UsrMerge” layout where /bin, /lib, /sbin etc. are symlinks into /usr. Most modern distros (including Ubuntu 20.04+, Debian Bookworm+, Arch) already do this, so this is mostly a non-issue now. The real layout constraint is that bootc wants:
/usr— immutable OS content (read-only at runtime)/etc— mutable config with 3-way merge/var— mutable persistent data
A traditional distro install scatters mutable state across more places and packages often write directly to /opt, /srv, /home during install scripts — things that don’t fit this model cleanly.
2. The bootloader problem (the hard one)
The main problem is that bootupd — which bootc relies on for bootloader management — uses hardcoded RHEL/Fedora-specific paths everywhere. It expects specific grub and shim package layouts, specific .efi file locations, and RPM as the package manager to query file ownership. For non-RPM distros (Debian/Ubuntu/Arch), you’d need to patch bootupd, and the patch is non-trivial. There’s an open tracking issue for generalizing bootupd for non-Fedora distributions. GitHubGitHub
3. The ostree version problem
Ubuntu and Debian currently have too-old an ostree package in their repos — bootc requires at least version 2025.03. So you can’t just apt install bootc on a stock Ubuntu base; you’d need to bring in a newer ostree from somewhere. GitHub
if you’re building something for production, use a Fedora/CentOS/RHEL/Alma base. If you need Ubuntu or Debian semantics badly enough, it’s feasible but you’re taking on integration work that Red Hat engineers haven’t prioritized yet.