Skip to content

VM-based runtime type (VMware / VirtualBox / QEMU / Parallels) complementing Docker #43

@djdarcy

Description

@djdarcy

VM-based runtime type (VMware / VirtualBox / QEMU / Parallels) complementing Docker

Status: design space open; preserved for future phase

Tracking issue for a future runtime.type: "vm" (or per-engine variants) to complement the Docker runtime shipped in v0.7.21. Addresses the gap between "tools that fit in a container" and "tools that need a full guest OS."

Not slated for any specific release. This issue preserves the design space. Companion issue to the test-matrix epic; both share the same VM-orchestration primitives but address different use cases.

Problem

The v0.7.21 Docker runtime dispatches tools that run in containers. Containers cover a lot -- most Linux-hostable tools, many arch-specific binaries, anything with a Dockerfile -- but they do NOT cover:

  1. Windows-only tools that need a Windows guest when the host is Linux or macOS. Windows containers exist but require a Windows host; a Mac user wanting to run a Win-only tool needs a VM.
  2. macOS-only tools (Apple silicon binaries, macOS system utilities). No Docker path; Mac-hardware + VM required.
  3. Legacy Windows tools (Win7/Win8.1/XP). Docker no longer supports; VMs persist indefinitely.
  4. BSD-specific tools (FreeBSD, OpenBSD, NetBSD, pfSense). Sparse Docker images; VMs are the native substrate.
  5. Exotic guest OSes (Haiku, FreeDOS, Plan 9, AIX, Solaris derivatives). Only VMs make this expressible.
  6. Tools requiring kernel-level features not exposed by container runtimes (custom drivers, hypervisor calls, GPU passthrough in strict modes).
  7. Tools requiring full stateful environments (a pre-configured development environment, licensed software activated to a specific VM, domain-joined test environment).

Each of these is a real class of tool that a dazzlecmd user might want to dispatch via dz mytool. Docker alone doesn't cover them.

Proposed solution (design space, not a commitment)

A new runtime type (or family of types) for VM-based dispatch. Parallels the Docker runtime shipped in v0.7.21.

Manifest schema sketch (preliminary)

{
    "runtime": {
        "type": "vm",
        "engine": "vmware",
        "vm_id": "win11-test-dev",
        "guest_user": "testuser",
        "guest_auth": {
            "method": "ssh",
            "port": 2222,
            "key_path": "~/.ssh/vm_id_ed25519"
        },
        "command_template": "pwsh -Command {{cmd}}",
        "auto_start": true,
        "auto_stop": false,
        "snapshot_restore": "clean-state",
        "inner_runtime": {
            "type": "script",
            "interpreter": "pwsh"
        }
    }
}

Fields to consider (design-time, not locked):

  • engine: which VM tool (vmware, virtualbox, qemu, parallels, hyperv). Each has different CLI (vmrun, VBoxManage, qemu-system-*, prlctl, Start-VM).
  • vm_id: vendor-specific identifier (VMX path, VirtualBox UUID, QEMU name, etc.)
  • guest_user + guest_auth: how dz connects TO the guest to execute the tool. Options: SSH with key, guest-exec API (VMware Tools, VBoxManage guestcontrol, QEMU guest agent), or RDP/WinRM for Windows guests.
  • command_template: how the tool's argv becomes a guest-runnable command (analog to Docker's ENTRYPOINT + argv passthrough).
  • auto_start / auto_stop: whether dz boots/shuts down the VM per dispatch. Boot is slow (30-120s); leaving VMs running is common.
  • snapshot_restore: optionally revert to a clean snapshot before each dispatch (test-run isolation).
  • inner_runtime: informational (matches Docker's pattern).

Engine-specific subtypes vs unified vm type

Two shapes:

A: Unified vm type with engine field (as sketched above).

  • Pros: one runtime type; schema discrimination via engine.
  • Cons: each engine has very different CLI; lots of conditional logic per field.

B: Per-engine runtime types (vmware, virtualbox, qemu, parallels, hyperv).

  • Pros: each factory is clean; no shared ambiguity.
  • Cons: proliferates types; manifest schema fragments by engine.

Probable answer: A (unified vm + engine field), mirroring how the node runtime uses an interpreter field (bun/deno/tsx) rather than separate bun/deno/tsx types.

Dispatch complexity vs Docker

Dimension Docker VM
Cold-start time 1-3s 30-120s
State model Mostly ephemeral; --rm makes it trivial Stateful; snapshots needed for reproducibility
Auth/command delivery CLI argv passthrough SSH / guest-exec API / WinRM
Image distribution Docker Hub (universal) OVF/OVA + vendor marketplaces; often manual
Licensing Free (CE) / paid Desktop Often paid (VMware Workstation, Fusion, Parallels)
Multi-platform host Docker Desktop covers Mac/Windows/Linux Each engine has its own per-host story
Cleanup docker rm trivial VM cleanup requires stopping + deleting + snapshot management

This is why VM is a separate commitment from Docker: different dispatch semantics, different lifecycle management, different performance characteristics.

Engine coverage priority (design guidance)

If this lands, which engines should ship first?

  • VirtualBox: free, cross-platform, CLI (VBoxManage) -- good MVP target
  • VMware Workstation/Fusion: commonly owned on macOS; vmrun CLI -- second priority
  • QEMU: Linux-native, free, scriptable -- covers Linux dev use cases
  • Hyper-V: Windows 10+ Pro has it built-in -- PowerShell-controllable
  • Parallels: macOS-specific; paid -- fourth priority
  • libvirt: Linux abstraction layer over multiple backends -- could be a meta-engine

Suggested MVP: VirtualBox (free, cross-platform) + VMware (paid, widely owned). Others as demand surfaces.

Relationship to other issues

Prior art

  • Vagrant: declarative VM configuration + provisioning. Excellent conceptual match but heavier than what dz needs.
  • Molecule (Ansible): VM-backed role testing. Uses delegates to drive VirtualBox/Docker/AWS.
  • Packer: VM image building. Not quite the same (builds vs runs), but shares engine abstraction.
  • act (GitHub Actions local runner): runs workflows in containers. Analogous to Docker runtime type A. No VM equivalent.
  • Vagrant's provider abstraction is the cleanest prior art -- a single entry point with pluggable engine drivers.

Acceptance criteria (placeholder)

Intentionally loose; a future dev-workflow-process will refine:

  • Design decision: unified vm type vs per-engine types
  • make_vm_runner() factory (or per-engine factories)
  • Engine abstraction layer (minimum: start / stop / exec-in-guest / snapshot-restore)
  • Pre-flight checks (VM tool installed + VM exists + guest is bootable)
  • Auth / command delivery mechanism (SSH as default; guest-exec API as fallback)
  • Support at least VirtualBox + VMware as MVP engines
  • Conditional dispatch integration (same platforms.<os> pattern as Docker)
  • _vars substitution support
  • dz info displays VM-specific fields
  • Documentation in docs/guides/ with worked examples per engine
  • Human test checklist + tester-agent validation

Non-goals (for this issue)

  • VM provisioning / image building (that's Packer's territory; out of scope)
  • Kubernetes / k3s / Docker Swarm orchestration
  • Cloud-VM substrates (EC2, GCE, Azure VMs) -- adjacent but a different issue
  • Hypervisor API direct integration (KVM, Xen, ESXi) -- would need a separate engine driver

Related

Project-private docs:

  • notes/ideas/2026-04-18__13-41-11__both_docker-and-vmware-for-cross-environment-testing.md -- originating note
  • 2026-04-18__00-01-23__dev-workflow-process_option-a-docker-runtime-v0.7.21.md -- the parallel Docker runtime design

Metadata

Metadata

Assignees

No one assigned

    Labels

    architectureStructural and design decisionsenhancementNew feature or requestepicLarge feature area tracking multiple tasksideasBrainstorming and future feature ideasroadmapProject direction and milestones

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions