Many tutorials cover converting physical disks to virtual images, but transforming a directory structure into a bootable virtual disk presents unique challenges. The key steps involve:
- Creating a properly sized virtual disk container
- Formatting it with a filesystem
- Mounting both the virtual disk and source directory
- Copying contents while preserving permissions
Here's the complete workflow I've tested on Ubuntu 22.04 LTS:
# 1. Create raw disk image (adjust size as needed)
qemu-img create -f raw disk.img 10G
# 2. Format the image (ext4 example)
mkfs.ext4 disk.img
# 3. Create mount points
mkdir /mnt/vdisk /mnt/source
# 4. Mount both devices
mount -o loop disk.img /mnt/vdisk
mount --bind /var/backups/disk1 /mnt/source
# 5. Copy contents (rsync preserves permissions)
rsync -avxHAX /mnt/source/ /mnt/vdisk/
# 6. Cleanup
umount /mnt/vdisk
umount /mnt/source
For better storage efficiency with KVM/QEMU:
# Convert raw to qcow2 format
qemu-img convert -f raw -O qcow2 disk.img disk.qcow2
# Optional: Compress the image
qemu-img convert -c -O qcow2 disk.qcow2 disk_compressed.qcow2
For repeated conversions, save this as dir_to_vdisk.sh
:
#!/bin/bash
SOURCE_DIR="$1"
OUTPUT_FILE="$2"
SIZE_GB="${3:-10}" # Default 10GB
# Create and format image
qemu-img create -f raw "$OUTPUT_FILE.raw" "${SIZE_GB}G"
mkfs.ext4 "$OUTPUT_FILE.raw"
# Mount and copy
mkdir -p /mnt/vdisk /mnt/source
mount -o loop "$OUTPUT_FILE.raw" /mnt/vdisk
mount --bind "$SOURCE_DIR" /mnt/source
rsync -avxHAX /mnt/source/ /mnt/vdisk/
# Convert to qcow2
qemu-img convert -f raw -O qcow2 "$OUTPUT_FILE.raw" "$OUTPUT_FILE.qcow2"
# Cleanup
umount /mnt/vdisk
umount /mnt/source
rm "$OUTPUT_FILE.raw"
Test your new image with QEMU:
qemu-system-x86_64 -enable-kvm -m 2048 \
-drive file=disk.qcow2,format=qcow2
When dealing with virtual machines, there are situations where you need to convert an existing directory structure (containing a complete filesystem) into a bootable virtual disk image. This differs significantly from physical disk conversion because:
- We're working with files rather than block devices
- The directory lacks partition table and boot sector information
- Filesystem metadata needs proper reconstruction
Here's the complete workflow to create a bootable virtual disk from your directory:
# Create raw image file
dd if=/dev/zero of=vmdisk.img bs=1M count=2048
# Format with filesystem
mkfs.ext4 vmdisk.img
# Mount and copy files
mkdir /mnt/vmdisk
mount -o loop vmdisk.img /mnt/vmdisk
rsync -a /var/backups/disk1/ /mnt/vmdisk/
umount /mnt/vmdisk
# Convert to QCOW2 format
qemu-img convert -f raw -O qcow2 vmdisk.img vmdisk.qcow2
For simpler cases, the virt-make-fs
tool from libguestfs can handle this in one command:
virt-make-fs --format=qcow2 --size=+2G /var/backups/disk1 vmdisk.qcow2
To make the image properly bootable, you'll need to:
- Install bootloader (GRUB):
- Ensure proper fstab entries:
mount -o loop vmdisk.img /mnt/vmdisk
grub-install --root-directory=/mnt/vmdisk --no-floppy --target=i386-pc vmdisk.img
umount /mnt/vmdisk
echo "/dev/vda1 / ext4 defaults 0 1" >> /mnt/vmdisk/etc/fstab
Test your new image with QEMU:
qemu-system-x86_64 -enable-kvm -m 2048 -hda vmdisk.qcow2
For production environments, consider these optimizations:
- Use
virt-sparsify
to shrink the image - Enable compression during conversion:
qemu-img convert -c -O qcow2
- Preallocate space with
fallocate
for better performance