Show HN: Lumier – Run macOS VMs in a Docker
When building virtualized environments for AI agents, we needed a reproducible way to package and distribute macOS VMs. Inspired by projects like dockur/windows (https://github.com/dockur/windows) that pioneered running Windows in Docker, we wanted to create something similar but optimized for Apple Silicon. The existing solutions either didn't support M-series chips or relied on KVM/Intel emulation, which was slow and cumbersome. We realized we could leverage Apple's Virtualization Framework to create a much better experience.
Lumier takes a different approach: it uses Docker as a delivery mechanism (not for isolation) and connects to a lightweight virtualization service (lume) running on your Mac. This creates true hardware-accelerated VMs using Apple's native virtualization capabilities.
With Lumier, you can: - Launch a ready-to-use macOS VM in minutes with zero manual setup - Access your VM through any web browser via VNC - Share files between your host and VM effortlessly - Use persistent storage or ephemeral mode for quick tests - Automate VM startup with custom scripts
All of this works natively on Apple Silicon (M1/M2/M3/M4) - no emulation required.
To get started:
1. Install Docker for Apple Silicon: https://desktop.docker.com/mac/main/arm64/Docker.dmg
2. Install lume background service with our one-liner:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/trycua/cua/main/libs/lume/scripts/install.sh)"
3. Start a VM (ephemeral mode): docker run -it --rm \
--name lumier-vm \
-p 8006:8006 \
-e VM_NAME=lumier-vm \
-e VERSION=ghcr.io/trycua/macos-sequoia-cua:latest \
-e CPU_CORES=4 \
-e RAM_SIZE=8192 \
trycua/lumier:latest
4. Open http://localhost:8006/vnc.html in your browser. The container will generate a unique password for each VM instance - you'll see it in the container logs.For persistent storage (so your changes survive container restarts):
mkdir -p storage docker run -it --rm \ --name lumier-vm \ -p 8006:8006 \ -v $(pwd)/storage:/storage \ -e VM_NAME=lumier-vm \ -e HOST_STORAGE_PATH=$(pwd)/storage \ trycua/lumier:latest
Want to share files with your VM? Just add another volume:
mkdir -p shared docker run ... -v $(pwd)/shared:/shared -e HOST_SHARED_PATH=$(pwd)/shared ...
You can even automate VM startup by placing an on-logon.sh script in shared/lifecycle/.
We're seeing people use Lumier for: - Development and testing environments that need macOS - CI/CD pipelines for Apple platform apps - Disposable macOS instances for security research - Automated UI testing across macOS versions - Running AI agents in isolated environments
Lumier is 100% open-source under the MIT license. We're actively developing it as part of our work on C/ua (https://github.com/trycua/cua), and we'd love your feedback, bug reports, or feature ideas.
We'll be here to answer any technical questions and look forward to your comments!
What’s the difference between this vs just using your lume CLI? Right now it feels like a worse interface to lume, but maybe I’m not getting a use case for this.
Also, any thoughts on https://github.com/cirruslabs/tart? (alas, not open source)
On a comparison with Tart, UTM, Lima, we actually touch it in this GitHub discussion: https://github.com/trycua/cua/issues/10
> aligning to a container interface here seems a natural step for us
It might be tricky since you do have to escape from the container to run the actual VM, though I guess you can figure something out here. I still think it’s the wrong layer to build your abstractions upon, but let’s see how it goes! Just don’t discontinue the CLI, it’s really cool :-)
Apple should recognize the use case or utility and run with it.
Usually they are responsive to these feedbacks, we'll try to mention on a existing GH issue: https://github.com/Developer-Ecosystem-Engineering
With Apple's RAM prices?
Since the host is already macOS, we leverage the Apple Virtualization Framework (Vz) directly via a lightweight background service (lume). The Docker container (Lumier) acts purely as a frontend and delivery mechanism for managing and launching VMs — there's no nested virtualization or Linux VM involved.
That said, you're absolutely right that macOS hardware isn’t cheap, and RAM can be a real constraint. If you're running multiple VMs or aiming for production-scale setups, options like Scaleway’s M4 Mac minis or EC2 Mac Metal instances offer more headroom.
Also worth noting: while Lumier supports virtualizing Linux VMs too, if your use case is only Linux, there are far more cost-effective options using KVM on Linux hosts.
Also there's some permanently running service. What's the point, to save 30 milliseconds out of the time to set up a VM which is certainly measured in tens of seconds?
(This is coming from someone who keeps colima running all the time on my Mac)
You're right that Docker on macOS runs inside a lightweight Linux VM (via Docker Desktop or Colima). We’re not using that VM to run the macOS guests - those run directly on the host via Apple’s Vz — but we do use Docker as a packaging and management layer (e.g. bundling noVNC, CLI tools, and configs).
So is it strictly necessary? Not really. But for teams already using Docker in CI/CD or automated workflows, it's often a tradeoff they're already making - and it means one less new tool/interface to adopt.
That said, we’re also looking into potentially using nested virtualization within the Docker daemon (which relies on Apple Vz under the hood) on M3+ chips, so as to remove the background service on the host entirely
Notably, Scaleway is one of the few providers to offer M4-based Mac minis that support nested virtualization. The main caveat is that these are currently only available in EU regions.
There’s instead no such limitation when running Linux VMs on a macOS host.
Currently, lume supports pushing to GitHub Container Registry (GHCR). However, it’s feasible to extend support to any OCI-compatible registry in the future.
Steps to build and push a custom image:
1. Start by creating a new VM or pulling an existing image. Launch the VM, make your desired modifications, and use it as your golden image.
2. Generate a classic access token on GitHub. Then: export GITHUB_USERNAME=<your_github_username> export GITHUB_TOKEN=<your_github_token>
3. Push your custom image: lume push "<VM_NAME_TO_PUSH>" "<IMAGE_NAME>:<TAG>" --registry ghcr.io --organization "<your_org_id>" --additional-tags "<optional_additional_tags>"
Example: lume push "lume_vm" "macos-sequoia-cua:latest" --registry ghcr.io --organization "trycua" --additional-tags "15.2"
Pull your image later with: lume pull "macos-sequoia-cua:latest" --registry ghcr.io --organization "trycua"
There is no mandatory dependency on the Cua-hosted registry - you are free to maintain your own image registry using GHCR or another OCI-compatible alternative (with some extension work).
I'm excited to play with lume! My use case is adding native Mac execution to Dagger (https://dagger.io) :)