This guide covers the optional iPXE workflow for Docker-VM-Runner. When enabled, the container injects an iPXE ROM into the primary network interface so the guest can chainload a remote installer or boot script. The ROM is auto-selected based on the NIC model (e.g. pxe-virtio.rom for virtio, pxe-e1000.rom for e1000).
IPXE_ENABLE=1must be set when starting the container.- The image ships with iPXE ROMs via
ipxe-qemu:x86_64→/usr/share/qemu/pxe-virtio.romaarch64→/usr/share/qemu/efi-virtio.rom
- For realistic PXE/iPXE environments, prefer
NETWORK_MODE=bridgeorNETWORK_MODE=directso the guest reaches your upstream DHCP/TFTP/HTTP services. User-mode NAT exposes only QEMU’s built-in DHCP/TFTP service.
docker run --rm -it \
--name vm-netboot \
--device /dev/kvm:/dev/kvm \
-e IPXE_ENABLE=1 \
-e BOOT_ORDER=network,hd \
-e NETWORK_MODE=bridge \
-e NETWORK_BRIDGE=br0 \
ghcr.io/munenick/docker-vm-runner:latestIPXE_ENABLE=1injects the ROM and automatically promotesnetworkto the highest boot priority.BOOT_ORDERcan includenetwork,hd, andcdrom. The manager ensuresnetworkis first whenever iPXE is enabled.- With bridge or direct networking, the guest acquires an address from your upstream DHCP server and follows your TFTP/HTTP boot profile.
Provide your own ROM by mounting it into the container and overriding IPXE_ROM_PATH:
docker run --rm -it \
--name vm-netboot \
--device /dev/kvm:/dev/kvm \
-e IPXE_ENABLE=1 \
-e IPXE_ROM_PATH=/images/ipxe/custom.rom \
-v "$PWD/ipxe:/images/ipxe:ro" \
ghcr.io/munenick/docker-vm-runner:latestOverride is mandatory when using an architecture that lacks a bundled ROM.
You can mix iPXE with cloud-init for post-boot configuration:
- Host an iPXE script on your infrastructure.
- Use an
#!ipxescript to chainload a kernel, or to fetch installation media. - Provide cloud-init metadata (e.g., via
BOOT_FROMpointing to an ISO, or a blank disk withcloud-init) to finish provisioning once the OS installer completes.
Example iPXE script snippet:
#!ipxe
dhcp
set base-url http://boot.example.com/images/alpine
kernel ${base-url}/vmlinuz alpine_repo=${base-url}/repo
initrd ${base-url}/initramfs
boot
- ROM not found: Confirm
ipxe-qemuis installed (bundled in the Dockerfile) or useIPXE_ROM_PATHto supply your own file. - Boot loops to disk: Ensure
BOOT_ORDERincludesnetworkand that no other device is listed ahead of it after iPXE promotion. - No network: Check bridge/direct permissions (
--cap-add NET_ADMINor--privilegedfor direct/macvtap), and confirm the upstream DHCP server is reachable. - User-mode NAT limitations: iPXE relies on DHCP options that QEMU’s built-in server might not expose. For production use, switch to
NETWORK_MODE=bridgeordirect.