One thing I loved but rarely mentioned is systemd-nspawn. You do `docker create --name ubuntu ubuntu:22.04` and then `docker export ubuntu` to create a tar from an arbitrary docker image. Then you extract that to `/var/lib/machines/ubuntu`. Make sure to choose an image with systemd or install systemd in the container. Finally do `machinectl start ubuntu` and `machinectl shell ubuntu` to get inside.
systemd-nspawn is very simple and lightweight and emulates a real Linux machine very well. You can take an arbitrary root partition based on systemd and boot it using systemd-nspawn and it will just work.
systemd-nspawn is simple but AFAIK it doesn't do any security other than the kernel namespacing. Docker is even worse because it runs containers as root, which means a rogue process can take over the host very easily.
Incus/LXD runs containers as normal users (by default) and also confines the whole namespace in apparmor to further isolate containerized processes from the host. Apparmor confinement is also used for VMs (the qemu process cannot access anything that is not defined in the whitelist)
``` incus launch images:ubuntu/22.04 --vm my-ubuntu-vm ```
After launching, access a shell with:
``` incus exec my-ubuntu-vm /bin/bash ```
Incus/LXD also works with system containers.