Run qemu/kvm VM inside a docker container
mkdir tmp && cp tmp
wget https://dl-cdn.alpinelinux.org/alpine/v3.19/releases/x86_64/alpine-virt-3.19.1-x86_64.iso
docker run --name container-vm --rm -v $PWD:/storage --cap-add=NET_ADMIN \
--device=/dev/kvm -p 8080:8080 weiyang/container-vm run --iso /storage/alpine-virt-3.19.1-x86_64.iso
mkdir tmp && cp tmp
wget https://dl-cdn.alpinelinux.org/alpine/v3.19/releases/x86_64/alpine-virt-3.19.1-x86_64.iso
docker run --name container-vm --rm -v $PWD:/storage --cap-add=NET_ADMIN --device-cgroup-rule='c *:* rwm' \
-p 8080:8080 weiyang/container-vm run --macvlan --iso /storage/alpine-virt-3.19.1-x86_64.iso
Then you can:
- Open
http://localhost:8080
to visit VM graphic docker exec -it container-vm telnet 127.0.0.1 10000
to visit VM consoleCtrl-A-C
-> Qemu monitor consoleCtrl-]
+quit
to exit telnet
- Simplicity: Utilizes a clean, straightforward QEMU setup for hassle-free virtualization, focusing on ease of use.
- Flexibility: Offers full compatibility and extensibility with customizable configurations, catering to diverse needs and ensuring easy adaptability for future expansions.
- Native Performance: Delivers exceptional efficiency and optimal performance through the use of advanced technologies such as Tap, MacVlan, and KVM acceleration.
-
Download windows iso (
Win11_23H2_x64v2.iso
or tiny11) -
Download VirtIO from
https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio
(virtio-win.iso
)If the hard drive is not detected, remember to install the drivers from the VirtIO ISO
-
Start container
Linux
docker run --rm -v $PWD:/storage --cap-add=NET_ADMIN --device /dev/kvm \ -p 8080:8080 weiyang/container-vm run -c 4 -m 8192 \ --iso /storage/Win11_23H2_x64v2.iso windows --virtio-iso /storage/virtio-win.iso \ apply-disk -s 64G -n hda ext-args -- -cpu host
MacOS
docker run --rm -v $PWD:/storage --cap-add=NET_ADMIN --device-cgroup-rule='c *:* rwm' \ -p 8080:8080 weiyang/container-vm run --macvlan -c 4 -m 8192 \ --iso /storage/Win11_23H2_x64v2.iso windows --virtio-iso /storage/virtio-win.iso \ apply-disk -s 64G -n hda
On MacOS, rm `--device=/dev/kvm` and `ext-args -- -cpu host`
--cap-add=NET_ADMIN
is necessary for network configuration--device-cgroup-rule='c *:* rwm'
is necessary for macvlan, or disable by--no-macvlan
-c 4 -m 8192
4 cpu cores, 8G memory--iso /storage/Win11_23H2_x64v2.iso
add boot cdromwindows --virtio-iso /storage/virtio-win.iso
add virtio isoapply-disk -s 64G -n hda
create a 64G disk if not existsext-args -- -cpu host
host-passthrough cpu mode, all flags afterext-args --
will be passed to qemu- VirtIO iso is recommended for best performance
Install Mesa3D driver https://github.com/pal1000/mesa-dist-win/releases
- Run docker with
--device=/dev/dri
- Run image with
run *** --vga - ext-args -- -display egl-headless -device virtio-vga-gl
- Minimum capability requirement is
--cap-add=NET_ADMIN
, run with--no-accel
--device-cgroup-rule='c *:* rwm'
/--macvlan
will enable macvlan, otherwise use tap bridge--device=/dev/kvm
/--no-accel
will disable IO acceleration, not recommended
- Write custom shell script to
/tmp/setup.sh
, e.g.
set -e
apt update
apt install -y glusterfs-common
-
Run docker with
-v /tmp:/tmp
-
Run image with
run *** exec-sh -f /tmp/setup.sh
The testing for Podman is not yet complete; you may submit an Issue if needed.
- May need to add more capabilities, such as
--cap-add NET_RAW
- May need to add more devices, such as
--device=/dev/net/tun
Commands are chainable, e.g. `run xxx windows xxx apply-disk xxx port-forward xxx ext-args -- xxx xxx`
❯ python main.py run --help
Usage: main.py run [OPTIONS] COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]...
╭─ Options ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ --cpu -c INTEGER CPU cores [default: None] │
│ --mem -m INTEGER RANGE [x>=1] Memory size in MB [default: None] │
│ --arch [alpha|sparc|nios2|sh4|xtensa|avr|sparc64|riscv32|m68k|tricore|microblaze VM arch [default: x86_64] │
│ |cris|mipsel|sh4eb|aarch64|loongarch64|ppc|hppa|mips64el|or1k|i386|mips64 │
│ |rx|microblazeel|riscv64|xtensaeb|mips|x86_64|s390x|arm|ppc64] │
│ --iso TEXT ISO file path or drive url [default: None] │
│ --accel --no-accel Enable acceleration [default: accel] │
│ --macvlan --no-macvlan Enable macvlan network, otherwise use bridge network [default: no-macvlan] │
│ --netdev --no-netdev Setup netdev or not [default: netdev] │
│ --dhcp --no-dhcp Enable DHCP [default: dhcp] │
│ --vnc-web --no-vnc-web Enable VNC web client (noVNC) [default: vnc-web] │
│ --console --no-console Enable Qemu monitor (mon+telnet+qmp) [default: console] │
│ --machine TEXT Machine type [default: None] │
│ --boot STR_OR_NONE Boot options (Set to '-' to disable) [default: once=dc] │
│ --vga STR_OR_NONE Setup VGA (Set to '-' to disable) [default: virtio] │
│ --boot-mode [uefi|secure|windows|legacy] Boot mode [default: legacy] │
│ --iface TEXT (multiple) Special VM network interface (e.g. eth1) │
│ --network TEXT (multiple) Special VM network CIDR (IPv4) (e.g. 192.168.1.0/24) │
│ --dry --no-dry Dry run [default: no-dry] │
│ --help Show this message and exit. │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Commands ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ apply-disk Apply VM disk │
│ exec-sh Exec shell script files before start Qemu │
│ ext-args External Qemu args │
│ port-forward Forward VM ports │
│ windows Windows specific options │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
`run xxx apply-disk -s 64G -n hda apply-disk -s 32G -n hdb`
❯ python main.py run apply-disk --help
Usage: main.py run apply-disk [OPTIONS]
Apply VM disk
╭─ Options ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ * --name -n TEXT Disk name (e.g. disk1) [default: None] [required] │
│ --size -s TEXT Disk size (e.g. 32G) [default: 16G] │
│ --file-type TEXT Drive file type (e.g. qcow2,raw) [default: qcow2] │
│ --if-type TEXT Drive interface type (e.g. virtio,ide) [default: None] │
│ --opts TEXT External drive options (e.g. index=i,format=f) [default: None] │
│ --help Show this message and exit. │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
`run xxx windows --virtio-iso /storage/virtio-iso.iso`
❯ python main.py run windows --help
Usage: main.py run windows [OPTIONS]
Windows specific options
╭─ Options ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ --virtio-iso PATH Window virtio driver iso, download from https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio [default: None] │
│ --tpm --no-tpm Enable TPM [default: tpm] │
│ --help Show this message and exit. │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
`run xxx port-forward -p 22:22 -p 3389:3389`
Ports 22 and 3389 are set to forward automatically by default
❯ python main.py run port-forward --help
Usage: main.py run port-forward [OPTIONS]
Forward VM ports
╭─ Options ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ --port -p TEXT (multiple) Port forward spec (e.g. 80:8088) [default: None] │
│ --help Show this message and exit. │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
`run xxx ext-args -- -cpu host -netdev xxx`
❯ python main.py run ext-args --help
Usage: main.py run ext-args [OPTIONS] ARGS...
External Qemu args
╭─ Arguments ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ * args ARGS... External Qemu args [default: None] [required] │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Options ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ --help Show this message and exit. │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
`run xxx exec-sh -f xxx.sh`
❯ python main.py run exec-sh --help
Usage: main.py run exec-sh [OPTIONS]
Exec shell script files before start Qemu
╭─ Options ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ --file -f PATH (multiple) shell script file [default: None] │
│ --help Show this message and exit. │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
MIT