💻 Windows in Docker Container
Discover an innovative and efficient method of deploying Windows OS (x64) on your Linux system using the power of Vagrant VM, libvirt, and docker-compose. Together, these technologies help you containerize Windows OS, enabling you to manage a Windows instance just as you would any Docker container. This seamless integration into existing workflows significantly enhances convenience and optimizes resource allocation.⭐ Don't forget to star the project if it helped you!
📋 Prerequisites
Ensure your system meets the following requirements:
- Docker: Version 20 or higher (Install Docker)
- Host OS: Linux
- Virtualization Enabled:
- Check with:
lscpu | grep -i Virtualization- Output indicates:
VT-x→ Intel virtualization is supported & enabled.AMD-V→ AMD virtualization is supported & enabled.- If virtualization is not enabled, enable it in the BIOS/UEFI settings.
cgroup: hostin the compose file is required: libvirt and the daemons it spawns need full cgroup access, otherwise the container fails to start on cgroup v2 hosts.
🚀 Deployment Guide
- Create/Update the environmental file
.env
# Vagrant image settings
MEMORY=8000 # MiB (~8 GB)
CPU=4
DISK_SIZE=100 # GiB
- Create
docker-compose.yml
services:
win10:
image: docker.io/vaggeliskls/windows-in-docker-container:latest
platform: linux/amd64
env_file: .env
stdin_open: true
tty: true
privileged: true
cgroup: host
restart: always
ports:
- 3389:3389
- 2222:2222
docker-compose.override.yml when you want your VM to be persistentservices:
win10:
volumes:
- libvirt_data:/var/lib/libvirt
- vagrant_data:/root/.vagrant.d
- vagrant_project:/app/.vagrant
- libvirt_config:/etc/libvirt
volumes:
libvirt_data:
name: libvirt_data
vagrant_data:
name: vagrant_data
vagrant_project:
name: vagrant_project
libvirt_config:
name: libvirt_config
- Run:
docker compose up -d
docker compose logs -f.When you want to destroy everything docker compose down -v
🌐 Access
Remote Desktop (RDP)
For debugging or testing, you can connect to the VM using Remote Desktop on port3389. #### Software for Remote Desktop Access
| OS | Software |
|----------|----------------|
| Linux | rdesktop → rdesktop or Remmina |
| MacOS | Microsoft Remote Desktop |
| Windows | Built-in Remote Desktop Connection |
SSH
You can connect via SSH using either the administrator or Vagrant user credentials.ssh @ -p 2222 🔑 User Login
Default users based on the Vagrant image are:- Administrator
- Username: Administrator
- Password: vagrant
- User
- Username: vagrant
- Password: vagrant
⚠️ Limitations
- Linux host only — depends on
/dev/kvmand libvirt; macOS and Windows hosts are not supported. - Eval license — the underlying box ships an evaluation copy of Windows Server 2022. Activation expires per Microsoft's eval terms.
- No synced folders —
rsync,smb, andnfsare all unwired in the Vagrantfile (rsync needs a Windows-side install before provisioning runs; SMB synced folders aren't supported with a Linux host; in-container NFS hitsno support in current kernel). - Performance — without nested KVM available to Docker (e.g. on a cloud VM that doesn't expose KVM), the guest falls back to plain QEMU and is several times slower.
🔧 Troubleshooting
KVM acceleration is not availablein logs → the host isn't exposing/dev/kvm. Check virtualization is enabled in BIOS, thekvmmodule is loaded (lsmod | grep kvm), and/dev/kvmexists on the host. The startup script falls back to QEMU automatically; expect a large slowdown.- Port 3389 / 2222 already in use → another RDP/SSH service is bound on the host. Stop it, or change the host-side port mapping in
docker-compose.yml. - Container exits immediately → almost always a cgroup or privilege problem. Confirm
privileged: trueandcgroup: hostare set, then checkdocker compose logs win10. vagrant uphangs at "Waiting for domain to get an IP address" → libvirt's default NAT network isn't running. Restart the container, or runvirsh net-start defaultfrom inside it.
📚 Further Reading and Resources
- Windows Vagrant Tutorial
- Vagrant image: peru/windows-server-2022-standard-x64-eval
- Vagrant by HashiCorp
- Windows Virtual Machine in a Linux Docker Container
- GPU inside a container