Container vs microVM for running untrusted code
Updated October 24, 2026 .md
Short answer: Use a microVM when the code is untrusted. A container is a set of Linux namespaces and cgroups on the host's own kernel, so a kernel bug or a mounted Docker socket can let code out. A microVM gives the code its own kernel behind hardware virtualization, which is a much smaller boundary to attack. gVisor sits in between.
The three boundaries#
| Container | gVisor | MicroVM | |
|---|---|---|---|
| What isolates the code | Linux namespaces and cgroups | A user-space "application kernel" (the Sentry) that intercepts system calls | Hardware virtualization (KVM) plus the VMM |
| Kernel | Shared with the host | gVisor's own, in user space, on top of the host kernel | The guest's own kernel |
| Typical runtime | runc (Docker, containerd) | runsc | Firecracker, Cloud Hypervisor, or Kata Containers on top of them |
| Compatibility | Full Linux | Most of the Linux API; some calls and tools behave differently | Full Linux, including Docker and systemd inside |
| Overhead | Lowest | Low to moderate | A VM per sandbox |
What the projects themselves say#
- Docker: "When you start a container with docker run, behind the scenes Docker creates a set of namespaces and control groups for the container." The Docker daemon "requires root privileges unless you opt-in to Rootless mode", and "the docker group grants root-level privileges to the user." (Docker security, post-install)
- Docker, on its own agent sandboxes: "Unlike containers, which share the host kernel, a sandbox VM cannot access host processes, files, or resources outside its defined boundaries." Docker's architecture table rates a container with a socket mount as "Partial (namespaces)" isolation for "Trusted tools", and microVM sandboxes as "Full (hypervisor)" for "Autonomous agents". (isolation, architecture)
- gVisor: "gVisor was created in order to provide additional defense against the exploitation of kernel bugs by untrusted userspace code." On hardware-level attacks it notes that, even when hardware virtualization is used, "the host kernel or hypervisor is ultimately responsible for defending against attacks from within malicious guests." (gVisor security)
- Kata Containers: "lightweight virtual machines that feel and perform like containers, but provide stronger workload isolation using hardware virtualization technology." (katacontainers.io)
- Firecracker: "Customer workloads are simultaneously considered sacred (shall not be touched) and malicious (shall be defended against)." Its docs also say "the overall security of Firecracker microVMs ... depends on a well configured Linux host operating system", and that "all egress traffic from a guest is ... considered untrusted, and should be filtered at the host-level." (charter, README, design)
Common ways a container sandbox leaks#
- Mounting
/var/run/docker.sock. Whoever controls the daemon controls the host; Docker says thedockergroup is root-equivalent. --privilegedfor Docker-in-Docker. Gives up most of the container's isolation to make nested Docker work.- Kernel bugs. Every container on a host talks to the same kernel; one exploitable bug is a way out for all of them.
- Shared host resources. Host paths, host networking or a shared credentials file mounted in for convenience.
A microVM changes the first two from "dangerous" to "normal": the code gets its own Docker daemon and root inside its own VM. The third becomes a guest-kernel bug, which stays inside the VM unless it can also break the hypervisor.
A microVM doesn't make everything safe#
| Still your job | Why |
|---|---|
| Secrets you put inside | Code in the VM can read and send them |
| Outbound network | A misled agent can call out; filter egress or keep secrets short-lived |
| What you do with the output | Review code before you merge or deploy it |
| Snapshot clones | Firecracker's snapshot docs warn that identifiers, random seeds and tokens are copied into every VM restored from one snapshot |
Running untrusted code in a microVM on Sandboxer#
Each Sandboxer sandbox is a Cloud Hypervisor microVM with its own kernel. Sandboxes can't reach each other or our internal networks. Start one with none of your secrets, run the code, and delete it:
sbx new --no-env
sbx scp ./untrusted.py sb_k3v9x2mq:/home/user/
sbx exec sb_k3v9x2mq --timeout 300 "python3 untrusted.py"
sbx delete sb_k3v9x2mq --yesFor per-user sandboxes in your own product, create each one with noEnv through the API, so it never holds your credentials.
FAQ#
Is a Docker container secure enough for untrusted code?#
A plain container isolates with namespaces and cgroups on the shared host kernel; Docker's own architecture table rates the common agent setup, a container with the Docker socket mounted, as partial isolation for trusted tools, and microVMs as full isolation for autonomous agents. For code you don't trust, use a VM boundary.
What is the difference between gVisor and a microVM?#
gVisor runs a user-space kernel that intercepts the application's system calls, so the host kernel sees far fewer of them. A microVM gives the code a real guest kernel behind hardware virtualization. gVisor is lighter; a microVM is fully Linux-compatible, including Docker and systemd inside.
Are microVMs slower than containers?#
A microVM boots a kernel and has more memory overhead than a container. Firecracker documents boot to /sbin/init in <= 125 ms and <= 5 MiB of VMM overhead under its stated test conditions (specification). For agent workloads that run for minutes or hours, the startup difference rarely matters.
What is Kata Containers?#
A container runtime that runs each container or pod in a lightweight VM, using Cloud Hypervisor, Firecracker, QEMU or others. You keep the container workflow and get a VM boundary.
Can code escape a microVM?#
Mainly through a bug in the VMM or the host's KVM, through hardware side channels, or through a badly configured host. That is a much smaller target than the full Linux system-call interface a container shares. Firecracker and Cloud Hypervisor both add seccomp filters on the VMM process as defense in depth.
More guides
For running AI-written code we rank Sandboxer, Freestyle and E2B first: each gives code its own VM with an API or SDK and can pause with memory. Pick Daytona for Windows or GPUs, Modal or Northflank for GPUs at scale, E2B or Northflank to run in your own cloud, and Vercel Sandbox if your app lives on Vercel.
For coding agents we rank Sandboxer first: a full Ubuntu VM with Claude Code and Codex preinstalled, Docker, and stop-and-resume that keeps the agent's session in memory. Freestyle and Amp Orbs also keep memory across pauses. Pick E2B for prebuilt agent templates on open source, Docker Sandboxes for free local runs, and Codespaces if you live in GitHub.
The best Daytona alternatives depend on why you're switching. For a full Linux microVM on every sandbox with memory-saving stop and Docker, we rank Sandboxer first. E2B suits open source and self-hosting, Modal massive short-job fleets, Northflank bring-your-own-cloud with GPUs, and Vercel Sandbox apps on Vercel.
If you're leaving E2B for longer sessions or a fuller machine, we rank Sandboxer first, then Freestyle: both give each sandbox a full Linux VM that keeps memory across pauses, with Docker and no short session cap. Pick Daytona for Windows or GPUs, Northflank for bring-your-own-cloud, and stay on E2B if you need open source.