DEV Community

Boris Barac
Boris Barac

Posted on

You Might Not Need Docker: The Case for Lightweight, Headless VMs

Lately, whenever I need to run a quick experiment or spin up a localized environment with multiple moving pieces, I've completely stopped using Docker. Instead, I've been running full, headless Ubuntu virtual machines directly from my host terminal using Canonical's Multipass. And I love it.

It is using your native hypervisor (KVM on Linux, Hyper-V on Windows, or QEMU on macOS), it drops a clean Ubuntu environment onto your laptop with next to zero performance overhead.

The Zero-Friction Sandbox

Instead of wrestling with installation mirrors and configuration screens, Multipass treats virtual machines as disposable command-line primitives.

To spin up a basic machine (we'll name it devbox) and jump inside, the standard baseline looks like this:

# Spin up a fresh Ubuntu instance instantly
multipass launch --name devbox

# Drop straight into the VM's interactive bash shell
multipass shell devbox
Enter fullscreen mode Exit fullscreen mode

Running Headless Commands Directly

You don't actually have to open an interactive shell session just to execute a single task. If you want to fire off commands and capture the output straight back to your host terminal, you can leverage exec:

# Check the VM's kernel version without entering the shell
multipass exec devbox -- uname -a

# Remotely trigger an update and install packages
multipass exec devbox -- sudo apt update
multipass exec devbox -- sudo apt install -y nginx

# this is usually needed to run custom tools out of the shell
multipass exec devbox -- bash -c "source ~/.profile && command"
Enter fullscreen mode Exit fullscreen mode

Moving Files Between Host and VM

When you are experimenting with local scripts or configuration files, moving data in and out of the isolated environment shouldn't require setting up network shares or SSH keys. Multipass handles this natively with a built-in transfer primitive:

# Copy a local configuration script from your host into the VM
multipass transfer ./setup.sh devbox:/home/ubuntu/setup.sh

# Pull a generated log file or benchmark report back out to your host
multipass transfer devbox:/home/ubuntu/output.log ./output.log
Enter fullscreen mode Exit fullscreen mode

If a testing session gets messy or you corrupt a system-level networking rule, you don't spend hours debugging. You simply nuke the instance and wipe the slate clean:

# Obliterate the broken VM and purge its allocated storage
multipass delete devbox
multipass purge
Enter fullscreen mode Exit fullscreen mode

Infrastructure as Code: Local Automation via Cloud-Init

For more advanced experiments requiring multiple pre-installed binaries or specific user permissions, you can bypass manual setup entirely using cloud-init. This is the exact same industry-standard engine used by major cloud providers to bootstrap instances at launch.

If we need a repeatable baseline containing Redis and Git, we can define the required environment state inside a standard cloud-config.yaml file:

#cloud-config
users:
  - name: devuser
    sudo: ALL=(ALL) NOPASSWD:ALL
    shell: /bin/bash
packages:
  - redis-server
  - git
runcmd:
  - systemctl enable redis-server
  - systemctl start redis-server
Enter fullscreen mode Exit fullscreen mode

To parse this configuration block directly during the VM's hardware initialization phase, pass the file using the --cloud-init flag:

# Launch a fully customized, automated instance using the configuration file
multipass launch --name cache-layer --cloud-init cloud-config.yaml
Enter fullscreen mode Exit fullscreen mode

Instead of spending ten minutes manually running configuration commands every time you need a new sandbox, dropping this YAML into a directory gives you an identical baseline whenever you need it. If the configuration breaks or the environment gets contaminated, you just destroy the VM and re-run the exact same launch command.

Architecture Breakdown: Multipass vs. Docker

A common question that comes up is why use Multipass when you could just run a Docker container. The core distinction lies entirely in where the isolation boundaries are drawn across the system stack.

+-----------------------------------+     +-----------------------------------+
|          DOCKER ARCHITECTURE      |     |       MULTIPASS ARCHITECTURE      |
|                                   |     |                                   |
|  [App A]   [App B]   (Containers) |     |  [Systemd] [Kernel]  (Full VM)    |
|  +-----------------------------+  |     |  +-----------------------------+  |
|  |    Shared Host Kernel       |  |     |  |     Native Hypervisor       |  |
+--+-----------------------------+--+     +--+-----------------------------+--+
Enter fullscreen mode Exit fullscreen mode

Docker isolates user-space processes. The containers sit directly on top of your host machine's operating system kernel. This makes them incredibly fast and resource-efficient for deploying standardized applications or microservices, but they don't have true system autonomy.

Multipass isolates the entire operating system block. It boots a completely independent Linux kernel, initializes a standalone virtual network loop, and runs its own init system (systemd).

If your experiment requires testing firewall structures (iptables), adjusting low-level network parameters, running background daemons orchestrated by systemd, or managing separate kernel modules, a Docker container requires fragile workarounds. Multipass gives you a true server abstraction directly on your laptop. Or even if you just want to spin up 5 things.

Hope it was interesting, I hope you learned something new. Thx for reading.

Top comments (0)