supermachine 0.7.108

Run any OCI/Docker image as a hardware-isolated microVM on macOS HVF (Linux KVM and Windows WHP in progress). Single library API, zero flags for the common case, sub-100 ms cold-restore from snapshot.
Documentation
#[cfg(any(
    all(target_os = "linux", target_arch = "x86_64"),
    all(target_os = "macos", target_arch = "aarch64")
))]
mod supported {
    //! Run a process inside a baked guest via `Vm::exec`.
    //!
    //! ```sh
    //! cargo supermachine build --release --example exec
    //! target/release/examples/exec nginx:1.27-alpine -- /bin/sh -c 'echo from-guest && nginx -v 2>&1'
    //! ```

    use std::io::Read;

    use supermachine::{Image, Vm, VmConfig};

    pub(super) fn main() -> Result<(), Box<dyn std::error::Error>> {
        let mut args = std::env::args().skip(1);
        let image_ref = args.next().ok_or("usage: exec IMAGE [-- argv...]")?;
        // Skip a literal `--` separator if present.
        let mut argv: Vec<String> = args.collect();
        if argv.first().map(|s| s.as_str()) == Some("--") {
            argv.remove(0);
        }
        if argv.is_empty() {
            argv = vec![
                "/bin/sh".to_owned(),
                "-c".to_owned(),
                "echo hello && exit 0".to_owned(),
            ];
        }

        let image = Image::from_oci(&image_ref)?;
        let vm = Vm::start(&image, &VmConfig::new())?;

        let mut child = vm.exec_builder().argv(argv).spawn()?;

        // Drain stdout/stderr concurrently.
        let mut stdout = child.stdout().expect("stdout taken");
        let mut stderr = child.stderr().expect("stderr taken");

        let so = std::thread::spawn(move || {
            let mut buf = Vec::new();
            let _ = stdout.read_to_end(&mut buf);
            buf
        });
        let se = std::thread::spawn(move || {
            let mut buf = Vec::new();
            let _ = stderr.read_to_end(&mut buf);
            buf
        });

        let status = child.wait()?;
        let stdout_bytes = so.join().unwrap();
        let stderr_bytes = se.join().unwrap();

        print!("{}", String::from_utf8_lossy(&stdout_bytes));
        if !stderr_bytes.is_empty() {
            eprint!("{}", String::from_utf8_lossy(&stderr_bytes));
        }
        eprintln!("exit: {:?}", status.code());

        vm.stop()?;
        Ok(())
    }
}

#[cfg(any(
    all(target_os = "linux", target_arch = "x86_64"),
    all(target_os = "macos", target_arch = "aarch64")
))]
fn main() -> Result<(), Box<dyn std::error::Error>> {
    supported::main()
}

#[cfg(not(any(
    all(target_os = "linux", target_arch = "x86_64"),
    all(target_os = "macos", target_arch = "aarch64")
)))]
fn main() -> Result<(), Box<dyn std::error::Error>> {
    eprintln!("this example requires a linux-x86_64 (KVM) or macos-aarch64 (HVF) host; unsupported on this platform");
    Ok(())
}