Полноценная виртуальная машина внутри Docker с веб-интерфейсом
Иногда нужно быстро проверить сомнительный скрипт, протестировать установку софта на чистом дистрибутиве или развернуть окружение со специфичным ядром. Запускать ради этого VirtualBox лень, поднимать Proxmox на рабочем ноутбуке избыточно, а обычный Docker-контейнер не дает изоляции на уровне ядра.
Недавно наткнулся на репозиторий qemus/qemu. Проект упаковывает QEMU с ускорением KVM внутрь обычного Docker-контейнера и пробрасывает управление виртуальной машиной прямо в браузер.
Как устроен проект
По сути, перед нами обертка над QEMU, которая берет на себя всю рутину по настройке эмулятора, сети, дисков и noVNC-клиента. Вам не нужно вручную прописывать длинные флаги командной строки или возиться с XML-конфигами libvirt.
Всё управление сводится к передаче переменных окружения в docker-compose.yml. Образ сам скачивает нужный дистрибутив Linux, нарезает виртуальный диск, подключает KVM для околонативной скорости работы и открывает порт с веб-интерфейсом на порту 8006.
Контейнер подходит как для локальной разработки, так и для запуска виртуалок в Kubernetes или GitHub Codespaces.
Быстрый старт
Для запуска достаточно минимального compose-файла. Например, развернем Linux Mint:
services:
qemu:
image: qemux/qemu
container_name: qemu
environment:
BOOT: "mint"
RAM_SIZE: "4G"
CPU_CORES: "2"
devices:
- /dev/kvm
- /dev/net/tun
cap_add:
- NET_ADMIN
ports:
- 8006:8006
volumes:
- ./qemu_data:/storage
restart: always
stop_grace_period: 2m
После выполнения команды docker compose up -d сервис автоматически скачает ISO-образ Mint и запустит виртуализацию.
Переходим в браузере по адресу http://localhost:8006 и видим экран установки ОС. Никаких дополнительных VNC-клиентов ставить не придется.
# Если вы предпочитаете чистый Docker CLI:
docker run -it --rm --name qemu \
-e "BOOT=alpine" \
-p 8006:8006 \
--device=/dev/kvm \
--device=/dev/net/tun \
--cap-add NET_ADMIN \
-v "${PWD}/qemu_data:/storage" \
--stop-timeout 120 \
docker.io/qemux/qemu
Что умеет контейнер
Автоматическая загрузка дистрибутивов
В переменной BOOT можно указать короткое имя популярного дистрибутива. Скрипт знает, откуда стянуть свежие образы:
arch,debian,fedora,ubuntu,alpinekali,nixos,gentoo,mint,manjarorocky,alma,cachy,tails
Если нужной системы нет в списке заготовленных, можно передать прямую ссылку на любой образ:
environment:
BOOT: "https://dl-cdn.alpinelinux.org/alpine/v3.19/releases/x86_64/alpine-virt-3.19.1-x86_64.iso"
Контейнер распаковывает архивы на лету и поддерживает образы .iso, .qcow2, .vmdk, .vhdx и .vdi. Также можно смонтировать локальный файл напрямую в корень контейнера как /boot.iso.
Работа с дисками и памятью
По умолчанию виртуалка получает диск размером 64 ГБ в формате qcow2 внутри директории /storage. Изменить размер можно в любой момент через переменную DISK_SIZE: "128G".
Если на хосте заканчивается оперативная память, контейнер поддерживает memory ballooning. Это помогает динамически возвращать неиспользуемую память гостевой системы хосту.
Обмен файлами с хостом
Чтобы передать файлы между хостом и виртуалкой, используется протокол 9pfs:
volumes:
- ./my_host_folder:/shared
Внутри запущенной гостевой системы останется только смонтировать каталог:
mount -t 9p -o trans=virtio shared /mnt/shared
Проброс портов и полноценная сеть
При стандартном bridge-режиме Docker проброс портов настраивается привычным блоком ports. Чтобы пробросить SSH наружу:
ports:
- 8006:8006
- 2222:22
Если виртуалке нужен собственный IP-адрес в локальной сети (чтобы домашний роутер выдал ей отдельный адрес по DHCP), контейнер можно подключить через macvlan. В таком случае отпадает необходимость в постоянном маппинге портов.
Проброс реального оборудования
Через compose-файл можно прокидывать реальные физические накопители (/dev/sdb:/disk1) или USB-устройства, передавая их идентификаторы в QEMU:
environment:
ARGUMENTS: "-device usb-host,vendorid=0x1234,productid=0x5678"
devices:
- /dev/bus/usb
Системные требования и ограничения
Главный нюанс кроется в поддержке KVM.
Без прямого доступа к устройству /dev/kvm аппаратное ускорение работать не будет, а чистая программная эмуляция CPU сделает работу невыносимо медленной.
Где это работает гладко:
- Linux-хосты с поддержкой аппаратной виртуализации (Intel VT-x / AMD-V).
- Windows 11 с Docker Desktop или Podman Desktop при включенной вложенной виртуализации (nested virtualization).
Docker Desktop на macOS и Windows 10 в настоящее время не пробрасывает /dev/kvm внутрь контейнеров, поэтому запустить проект там не получится.
Проверить доступность KVM на Linux можно стандартной утилитой:
sudo apt install cpu-checker
sudo kvm-ok
Если команда выдает KVM acceleration can be used, контейнер запустится без проблем.
Для чего это можно использовать
- Тестирование сценариев автоматизации. Запуск чистых инсталляций Ansible или bash-скриптов в изолированной виртуалке без риска сломать рабочую систему.
- Безопасный запуск софта. Проверка подозрительных пакетов или бинарников в изолированном окружении, которое можно пересоздать одной командой.
- Обучение и эксперименты. Знакомство с новыми дистрибутивами (например, NixOS или Alpine) прямо в окне браузера без возни с флешками.
- CI/CD пайплайны. Сборка пакетов ядра или тестирование системного софта внутри полноценных виртуальных машин на раннерах Kubernetes.
Резюме
Проект qemus/qemu отлично закрывает нишу между легковесными контейнерами и тяжелыми гипервизорами. Если вам регулярно требуются изолированные виртуальные машины для тестов на Linux-машине или домашнем сервере, этот образ экономит массу времени на подготовке образов и настройке сети.
Репозиторий активно поддерживается организацией qemus, у них также есть отдельные адаптированные сборки под ARM64, Windows и macOS.
