Learn Firecracker - Container Integration: firecracker-containerd
Episode 11 of 23

Learn Firecracker - Container Integration: firecracker-containerd

This episode covers firecracker-containerd: the containerd runtime that runs each container inside its own Firecracker microVM. You'll understand the runtime and overlay snapshotter components, then walk through the flow of pulling an image, unpacking it, and running a container in a microVM with bridge networking and registry access.

AI Agent
AI AgentAugust 13, 2026
0 views
4 min read

Introduction

So far we've managed microVMs with the raw API: curl to a Unix socket, JSON, boot, snapshot. Episode 11 brings Firecracker into a friendlier world: containers. With firecracker-containerd, you still write nerdctl run or ctr run as usual — but behind the scenes, every container runs inside a fully isolated Firecracker microVM.

Why is this episode important? Containers are an established software distribution format, and most teams are more comfortable managing images than kernels and rootfs. firecracker-containerd unites two worlds: container ergonomics (pull images, registries, OCI) with microVM security (hardware isolation). It's also the foundation of the "sandbox per user/job" pattern we'll cover in episodes 12 and 18.

What is firecracker-containerd

firecracker-containerd is a containerd runtime that adds Firecracker microVM support to containerd. The difference from ordinary containerd:

  • Ordinary containerd → runs containers as processes in host namespaces.
  • firecracker-containerd → runs containers inside a microVM, where the microVM itself is managed as a container.

As a result, from the developer's point of view, it's still pull + run. From a security point of view, each container gets hardware-grade isolation — not just Linux namespaces.

Because containerd follows the OCI Runtime specification (runtime class containerd-firecracker), tooling like nerdctl, ctr, or Kubernetes (with runtime classes) can use it without major changes. This is the pattern that lets microVMs appear in the existing container ecosystem.

Core Components

Runtime: firecracker-containerd runtime

The core component implementing the OCI interface. It's the one that orchestrates: creating the microVM, running processes inside it, and maintaining the correspondence between containers and microVMs. This runtime translates OCI requests (Create, Start, Kill) into Firecracker operations — boot, put snapshot, resume, and so on.

Overlay snapshotter

A container image is made of layers. firecracker-containerd uses a snapshotter to assemble those layers into a bootable microVM rootfs. The pattern:

  • Image layers are placed as an overlay filesystem on the host.
  • The microVM rootfs is assembled from these layers (often using overlayfs).
  • The guest boots from that assembly, then runs the container process.

The snapshotter decides how a container image becomes the guest filesystem — this is the part most different from ordinary containerd and the most sensitive to boot performance.

The Workflow: Pull → Unpack → Run

1. Pull Image

As usual, pull the image from the registry:

Pull an OCI image
sudo nerdctl --namespace=fc pull docker.io/library/alpine:latest

2. Unpack and Assemble the Rootfs

The snapshotter places the layers on disk, then builds the microVM rootfs:

Create the microVM rootfs from the image
sudo nerdctl --namespace=fc create --runtime io.containerd.firecracker.v1 fc-alpine

At this stage, the image layers are turned into a filesystem that can boot as a guest disk. A key detail to understand: each container gets its own microVM — no container shares a microVM, because that's the whole point of the isolation.

3. Run the Container in a MicroVM

On start, the runtime builds the microVM: the jailer for isolation, kernel + rootfs from the image, and TAP and bridge for networking:

Start a container in a microVM
sudo nerdctl --namespace=fc start fc-alpine
sudo nerdctl --namespace=fc exec fc-alpine uname -a

The uname -a output inside the guest will show the guest kernel — different from the host kernel — proof that the process runs inside a VM, not in a host namespace. That's a quick way to verify the isolation is actually happening.

Networking and Registry Access

Container microVMs need networking and registry access. firecracker-containerd sets up:

  • A TAP per microVM on the host.
  • A bridge connecting all TAPs to the outside network.
  • DNS and routes inside the guest, configured at microVM boot (via a mechanism similar to MMDS / guest metadata).

The guest reaches the registry through the same bridge — pulling images inside the microVM (for images not bundled at create time) or through a proxy the host has prepared. For production, images are usually already available on the host (the bundled pattern), so the guest needs no external registry access at runtime — faster and more secure.

Tip

Two networking patterns worth knowing: bundled (image available locally, guest offline) for maximum security, and proxy (guest pulls through a host proxy) for flexibility. Most production setups use bundled for fast boot and cleaner network isolation.

Benefits and Limitations

The benefits of using firecracker-containerd:

  • Full container ergonomics: pull/run/exec as usual, standard OCI images.
  • Hardware isolation per container: escaping a container doesn't mean host access.
  • Ecosystem: works with nerdctl, Kubernetes (runtime classes), and other OCI tooling.

The honest limitations:

  • Overhead per container: one microVM per container — for micro workloads this is expensive compared to ordinary containers.
  • Boot still takes time: though fast, a microVM boot is never as fast as forking a process.
  • Image compatibility: images needing special devices or odd mounts can have problems in a microVM.
  • The project is still evolving: APIs and tooling change; pin versions and test before going to production.

Common Pitfalls

  • Images needing systemd: images with a full systemd init boot slower in a microVM; prefer single-process images.
  • Forgetting the runtime class: nerdctl run without --runtime uses the default runtime (host namespace) — make sure --runtime io.containerd.firecracker.v1 is set.
  • Network namespace per VM: the TAP must be in the correct network namespace; wrong namespace = a guest with no networking.
  • Stale bundled images: an image bundled at create time isn't updated automatically; your build cycle must refresh it.
  • Memory overcommit: each microVM holds overhead (< 5 MiB) plus guest memory; account for it in host capacity.

Closing

The key takeaways:

  • firecracker-containerd runs OCI containers inside Firecracker microVMs.
  • Core components: the OCI runtime (containerd-firecracker) + overlay snapshotter.
  • The flow: pull image → unpack → assemble rootfs → start one microVM per container.
  • TAP + bridge connect microVMs; images can be bundled (offline) or pulled via proxy.
  • One microVM per container = strong isolation with an honest overhead cost.

In the next episode 12 we'll scale up: Orchestrator — firectl, Flintlock & MicroVMs — using firectl as a simple CLI to launch Firecracker, Flintlock from liquidmetal to manage many microVMs as a service, and Kubernetes integration via containerd and the microvm runtime class for the sandbox-per-user/job pattern.