Builds bootable Linux VM disk images from Docker. Supports Alpine and Debian, for both amd64 and arm64.
- A distro-specific Dockerfile builds a root filesystem (kernel + userspace) inside a Docker image.
Dockerfile.disk-imagerunsbuild-image.shwith elevated privileges to create a GPT disk image with an EFI System Partition (FAT32, GRUB) and a root partition (ext4, rootfs). The image is shrunk to fit its contents.- The final disk image is exported from the container to
output/<distro>/.
brew install qemu dockerDocker must support BuildKit with the security.insecure entitlement (required for loopback device operations inside the build container).
Build all distros for all architectures:
docker buildx bake --allow=security.insecureBuild a specific distro:
docker buildx bake disk-image-alpine --allow=security.insecure
docker buildx bake disk-image-debian --allow=security.insecureOutput images land in output/alpine/ and output/debian/, one per architecture (linux_amd64/disk.img, linux_arm64/disk.img).
Default credentials: root / root
qemu-system-aarch64 \
-machine virt,accel=hvf \
-cpu host \
-smp 4 \
-m 2048 \
-drive "if=pflash,format=raw,file=/opt/homebrew/share/qemu/edk2-aarch64-code.fd,readonly=on" \
-drive "if=virtio,format=raw,file=output/alpine/linux_arm64/disk.img" \
-nographic \
-serial mon:stdio \
-netdev user,id=net0 \
-device virtio-net-pci,netdev=net0To add a display (for debian-vscode for example):
qemu-system-aarch64 \
-machine virt,accel=hvf \
-cpu host \
-smp 4 \
-m 2048 \
-serial stdio \
-machine virt \
-drive "if=pflash,format=raw,file=/opt/homebrew/share/qemu/edk2-aarch64-code.fd,readonly=on" \
-drive "if=virtio,format=raw,file=disk.img" \
-device virtio-gpu \
-display default \
-device usb-ehci \
-device usb-kbd \
-device usb-mouseqemu-system-x86_64 \
-machine q35 \
-cpu qemu64 \
-smp 2 \
-m 2048 \
-drive "if=pflash,format=raw,file=/opt/homebrew/share/qemu/edk2-x86_64-code.fd,readonly=on" \
-drive "if=virtio,format=raw,file=output/debian/linux_amd64/disk.img" \
-nographic \
-serial mon:stdio| Partition | Size | Type | Contents |
|---|---|---|---|
| 1 | 64 MiB | FAT32 | EFI + GRUB |
| 2 | variable | ext4 | root filesystem |
EFI partition is 64MiB by default but can be changed: docker buildx bake disk-image-alpine --allow=security.insecure --set "*.args.EFI_SIZE=100M".
The root partition is shrunk to the minimum size that fits the content, plus 10% headroom.