Pełnoprawna maszyna wirtualna wewnątrz Dockera z interfejsem webowym
Czasami trzeba szybko sprawdzić wątpliwy skrypt, przetestować instalację oprogramowania na czystej dystrybucji lub wdrożyć środowisko z określonym jądrem. Uruchomienie VirtualBoxa jest zbyt uciążliwe, konfigurowanie Proxmoxa na służbowym laptopie to przesada, a zwykły kontener Docker nie zapewnia izolacji na poziomie jądra.
Ostatnio natknąłem się na repozytorium qemus/qemu. Projekt pakuje QEMU z akceleracją KVM do zwykłego kontenera Docker i udostępnia zarządzanie maszyną wirtualną bezpośrednio w przeglądarce.
Jak działa projekt
W zasadzie to wrapper wokół QEMU, który zajmuje się całą żmudną konfiguracją emulatora, sieci, dysków i klienta noVNC. Nie musisz ręcznie pisać długich flag linii poleceń ani bawić się konfiguracjami XML libvirt.
Całe zarządzanie sprowadza się do przekazywania zmiennych środowiskowych do docker-compose.yml. Obraz automatycznie pobiera wymaganą dystrybucję Linuksa, tworzy wirtualny dysk, łączy KVM zapewniając niemal natywną wydajność i otwiera interfejs webowy na porcie 8006.
Kontener nadaje się zarówno do lokalnej pracy deweloperskiej, jak i do uruchamiania maszyn wirtualnych w Kubernetes lub GitHub Codespaces.
Szybki start
Aby go uruchomić, potrzebujesz tylko minimalnego pliku compose. Na przykład wdrożmy 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
Po uruchomieniu docker compose up -d usługa automatycznie pobiera obraz ISO Minta i uruchamia wirtualizację.
Przejdź do http://localhost:8006 w przeglądarce, a zobaczysz ekran instalacji systemu operacyjnego. Nie trzeba instalować żadnych dodatkowych klientów 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
Co potrafi kontener
Automatyczne pobieranie dystrybucji
W zmiennej BOOT możesz podać krótką nazwę popularnej dystrybucji. Skrypt wie, skąd pobrać najnowsze obrazy:
arch,debian,fedora,ubuntu,alpinekali,nixos,gentoo,mint,manjarorocky,alma,cachy,tails
Jeśli potrzebujesz systemu, którego nie ma na liście presetów, możesz przekazać bezpośredni link do dowolnego obrazu:
environment:
BOOT: "https://dl-cdn.alpinelinux.org/alpine/v3.19/releases/x86_64/alpine-virt-3.19.1-x86_64.iso"
Kontener rozpakowuje archiwa w locie i obsługuje obrazy w formatach .iso, .qcow2, .vmdk, .vhdx i .vdi. Możesz też zamontować lokalny plik bezpośrednio do katalogu głównego kontenera jako /boot.iso.
Praca z dyskami i pamięcią
Domyślnie maszyna wirtualna otrzymuje dysk 64 GB w formacie qcow2 w katalogu /storage. Rozmiar można zmienić w dowolnym momencie za pomocą zmiennej DISK_SIZE: "128G".
Jeśli na hoście zabraknie RAM, kontener obsługuje memory ballooning. Pomaga to dynamicznie zwracać nieużywaną pamięć gościa do hosta.
Wymiana plików z hostem
Do przesyłania plików między hostem a maszyną wirtualną używany jest protokół 9pfs:
volumes:
- ./my_host_folder:/shared
W działającym systemie gościa wystarczy zamontować katalog:
mount -t 9p -o trans=virtio shared /mnt/shared
Przekierowanie portów i pełna sieć
Przy standardowym trybie mostka Docker przekierowanie portów konfiguruje się przez znajomy blok ports. Aby przekierować SSH na zewnątrz:
ports:
- 8006:8006
- 2222:22
Jeśli maszyna wirtualna potrzebuje własnego adresu IP w sieci lokalnej (tak żeby router domowy przydzielił mu osobny adres przez DHCP), kontener można połączyć przez macvlan. W tym przypadku nie trzeba ciągłego mapowania portów.
Przekazywanie prawdziwego sprzętu
Przez plik compose można przekazać prawdziwe dyski fizyczne (/dev/sdb:/disk1) lub urządzenia USB, podając ich identyfikatory do QEMU:
environment:
ARGUMENTS: "-device usb-host,vendorid=0x1234,productid=0x5678"
devices:
- /dev/bus/usb
Wymagania systemowe i ograniczenia
Główna uwaga dotyczy obsługi KVM.
Bez bezpośredniego dostępu do urządzenia /dev/kvm akceleracja sprzętowa nie zadziała, a czysta emulacja CPU programowa sprawi, że wydajność będzie nie do zniesienia.
Gdzie to działa bezproblemowo:
- Hosty Linuksowe z obsługą wirtualizacji sprzętowej (Intel VT-x / AMD-V).
- Windows 11 z Docker Desktop lub Podman Desktop z włączoną zagnieżdżoną wirtualizacją.
Docker Desktop na macOS i Windows 10 obecnie nie przekazuje /dev/kvm do kontenerów, więc nie będziesz w stanie uruchomić projektu w tych środowiskach.
Możesz sprawdzić dostępność KVM na Linuksie standardowym narzędziem:
sudo apt install cpu-checker
sudo kvm-ok
Jeśli polecenie wyświetli KVM acceleration can be used, kontener uruchomi się bez problemów.
Do czego można tego użyć
- Testowanie scenariuszy automatyzacji. Uruchamianie czystych instalacji Ansible lub skryptów bash w izolowanej maszynie wirtualnej bez ryzyka zepsucia działającego systemu.
- Bezpieczne uruchamianie oprogramowania. Sprawdzanie podejrzanych pakietów lub plików binarnych w izolowanym środowisku, które można odtworzyć jednym poleceniem.
- Nauka i eksperymenty. Eksplorowanie nowych dystrybucji (np. NixOS czy Alpine) bezpośrednio w oknie przeglądarki bez bawienia się pendrive'ami.
- Pipeline'y CI/CD. Budowanie pakietów jądra lub testowanie oprogramowania systemowego w pełnych maszynach wirtualnych na runnerach Kubernetes.
Podsumowanie
Projekt qemus/qemu idealnie wypełnia niszę między lekkimi kontenerami a ciężkimi hiperwizorami. Jeśli regularnie potrzebujesz izolowanych maszyn wirtualnych do testowania na maszynie z Linuksem lub serwerze domowym, ten obraz oszczędza mnóstwo czasu na przygotowanie obrazów i konfigurację sieci.
Repozytorium jest aktywnie rozwijane przez organizację qemus, która ma też osobne dostosowane buildy dla ARM64, Windows i macOS.
Powiązane projekty