Skip to content

Repository files navigation

💻 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: host in 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

  1. Create/Update the environmental file .env
# Vagrant image settings
MEMORY=8000     # MiB (~8 GB)
CPU=4
DISK_SIZE=100   # GiB
  1. 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
  1. Create docker-compose.override.yml when you want your VM to be persistent
services:
  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
  1. Run: docker compose up -d

First boot takes several minutes — the Vagrant box is already baked into the image, but the VM still has to boot and run the provisioning script (Chocolatey install, disk resize, registry tweaks). Follow progress with docker compose logs -f.

When you want to destroy everything docker compose down -v

windows screenshot

🌐 Access

Remote Desktop (RDP)

For debugging or testing, you can connect to the VM using Remote Desktop on port 3389.

Software for Remote Desktop Access

OS Software
Linux rdesktoprdesktop <ip>:3389 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 <user>@<host> -p 2222

🔑 User Login

Default users based on the Vagrant image are:

  1. Administrator
    • Username: Administrator
    • Password: vagrant
  2. User
    • Username: vagrant
    • Password: vagrant

⚠️ Limitations

  • Linux host only — depends on /dev/kvm and 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 foldersrsync, smb, and nfs are 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 hits no 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 available in logs → the host isn't exposing /dev/kvm. Check virtualization is enabled in BIOS, the kvm module is loaded (lsmod | grep kvm), and /dev/kvm exists 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: true and cgroup: host are set, then check docker compose logs win10.
  • vagrant up hangs at "Waiting for domain to get an IP address" → libvirt's default NAT network isn't running. Restart the container, or run virsh net-start default from inside it.

📚 Further Reading and Resources

About

Deploy and manage a Windows OS (x64) seamlessly using Vagrant VM, libvirt, and docker-compose. This innovative approach integrates smoothly into existing workflows, providing an efficient way of containerizing Windows OS for better resource allocation and convenience.

Topics

Resources

Stars

117 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages