Jesse A. Green / notebook

Windows in a Docker Container — User Guide

Generated June 2026 from dockur/windows at 0c9472b

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

dockur/windows runs a full Microsoft Windows operating system inside a Docker container. It downloads the Windows installation media for you, performs a completely unattended installation, and gives you a running desktop you reach from your web browser or any Remote Desktop client — no manual setup, no product key hunting, no ISO wrangling.

This guide covers everything you need to install, configure, and operate a Windows container. It is written for end users running the published dockurr/windows image. For architecture, internals, security hardening, and the ISO download pipeline, see the companion Admin Guide.

Note

This container runs x64 versions of Windows. To run ARM64 Windows (for example on an Apple Silicon or Raspberry Pi host), use the sibling project dockur/windows-arm instead.


1. Quick Start

The fastest way to a running Windows 11 desktop:

Docker Compose

Create a file named compose.yml:

services:
  windows:
    image: dockurr/windows
    container_name: windows
    environment:
      VERSION: "11"
    devices:
      - /dev/kvm
      - /dev/net/tun
    cap_add:
      - NET_ADMIN
    ports:
      - 8006:8006
      - 3389:3389/tcp
      - 3389:3389/udp
    volumes:
      - ./windows:/storage
    restart: always
    stop_grace_period: 2m

Then start it:

docker compose up -d

Docker CLI

docker run -it --rm --name windows \
  -e "VERSION=11" \
  -p 8006:8006 \
  --device=/dev/kvm \
  --device=/dev/net/tun \
  --cap-add NET_ADMIN \
  -v "${PWD:-.}/windows:/storage" \
  --stop-timeout 120 \
  docker.io/dockurr/windows

Kubernetes

kubectl apply -f https://raw.githubusercontent.com/dockur/windows/refs/heads/master/kubernetes.yml

Once the container is running:

  1. Open http://127.0.0.1:8006/ in your web browser.
  2. Watch the fully automatic installation proceed. Nothing is required from you.
  3. When the Windows desktop appears, your machine is ready to use.
❯ Booting Windows using QEMU v9.x.x...
❯ Downloading Windows 11 Pro...
❯ Windows started successfully, visit http://127.0.0.1:8006/ to view the screen...

Tip

The default login created during installation is username Docker and password admin. You can change these — see Setting the username and password.

Important

Your host must support KVM hardware acceleration for the container to work. Most Linux hosts and Windows 11 (via WSL2) do; Windows 10 and macOS generally do not. Verify your system before troubleshooting anything else — see Verifying KVM support.


2. Requirements

Requirement Detail
CPU virtualization Intel VT-x or AMD SVM, enabled in BIOS/UEFI
KVM device /dev/kvm must be present and accessible on the host
TUN device /dev/net/tun for container networking
Capability NET_ADMIN added to the container
Disk space Enough for the Windows image (see size table in Section 3) plus your data — default virtual disk is 64G
Container runtime Docker, Podman, or Kubernetes

Host compatibility chart

Product Linux Windows 11 Windows 10 macOS
Docker CLI ✅ ✅ ❌ ❌
Docker Desktop ❌ ✅ ❌ ❌
Podman CLI ✅ ✅ ❌ ❌
Podman Desktop ✅ ✅ ❌ ❌

Warning

Most cloud providers do not permit nested virtualization on standard VPS instances, so KVM is unavailable there. If you run the container inside another virtual machine, you must enable "nested virtualization" on that VM first.


3. Selecting a Windows Version

By default, Windows 11 Pro is installed. Set the VERSION environment variable to choose a different edition. The image is downloaded automatically on first run.

environment:
  VERSION: "10"
VERSION Edition Approx. download
11 Windows 11 Pro (default) 7.9 GB
11l Windows 11 LTSC 4.7 GB
11e Windows 11 Enterprise 6.6 GB
10 Windows 10 Pro 5.7 GB
10l Windows 10 LTSC 4.6 GB
10e Windows 10 Enterprise 5.2 GB
8e Windows 8.1 Enterprise 3.7 GB
7u Windows 7 Ultimate 3.1 GB
vu Windows Vista Ultimate 3.0 GB
xp Windows XP Professional 0.6 GB
2k Windows 2000 Professional 0.4 GB
2025 Windows Server 2025 7.6 GB
2022 Windows Server 2022 6.0 GB
2019 Windows Server 2019 5.3 GB
2016 Windows Server 2016 6.5 GB
2012 Windows Server 2012 4.3 GB
2008 Windows Server 2008 3.0 GB
2003 Windows Server 2003 0.6 GB

Note

The VERSION field is flexible about how you write it. For Windows 11 Pro, any of 11, win11, pro11, windows11, or windows 11 all resolve to the same image. The same shorthand applies across every version.

Tip

The download sizes above are guidelines. Set DISK_SIZE large enough to hold both the installed OS and your future data — the default 64G is comfortable for most uses but small for heavy workloads.


4. Everyday Configuration

All configuration is done through environment variables in your compose.yml (or -e flags on the command line). The most common settings are below.

4.1 Set CPU and memory

By default Windows is allotted 2 CPU cores and 4 GB of RAM. Adjust with:

environment:
  RAM_SIZE: "8G"
  CPU_CORES: "4"

Caution

Allocating most or all of your host's cores can cause the host (and laptops especially) to run hot during the install phase, which is CPU-intensive. Leave headroom for the host operating system.

4.2 Change where data is stored

The container keeps the virtual disk and all Windows data in the /storage volume. Bind it to a host folder so your machine survives container recreation:

volumes:
  - ./windows:/storage

Replace ./windows with any host folder or named volume.

Important

If you remove the /storage bind mount, your Windows installation lives only inside the container and is lost when the container is deleted. Always bind /storage for anything you want to keep.

4.3 Set the username and password

A user named Docker with password admin is created during installation. To use your own credentials:

environment:
  USERNAME: "bill"
  PASSWORD: "gates"

Note

These credentials are applied during installation only. Changing them after Windows is installed has no effect — change the password from inside Windows instead.

4.4 Choose the Windows display language

The English edition is downloaded by default. To download a localized edition, set LANGUAGE to a language name:

environment:
  LANGUAGE: "French"

Supported languages: Arabic, Bulgarian, Chinese, Croatian, Czech, Danish, Dutch, English, Estonian, Finnish, French, German, Greek, Hebrew, Hungarian, Italian, Japanese, Korean, Latvian, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovenian, Spanish, Swedish, Thai, Turkish, and Ukrainian.

Warning

Localized editions are only available for the mainstream consumer versions (Windows 10/11 Pro). Older versions, LTSC/IoT, and most Server editions are English-only. Requesting another language for those will fail the download.

4.5 Set the keyboard layout and region

If you want a keyboard or regional locale that differs from the language default, set KEYBOARD and REGION explicitly (using BCP-47 culture codes such as en-US, de-DE, fr-CA):

environment:
  LANGUAGE: "English"
  REGION: "en-US"
  KEYBOARD: "en-US"

Configuration quick reference

Variable Default Purpose
VERSION 11 Windows edition to install (Section 3)
RAM_SIZE 4G Memory assigned to Windows
CPU_CORES 2 Virtual CPU cores assigned to Windows
DISK_SIZE 64G Size of the main virtual disk
USERNAME Docker Account created during install
PASSWORD admin Password for that account
LANGUAGE English Display language of the downloaded edition
REGION (language default) Regional/locale culture code
KEYBOARD (language default) Keyboard input locale
MANUAL (unset) Set Y to skip unattended setup (Section 7)
DHCP (unset) Set Y to give Windows its own router IP (Section 8)
ARGUMENTS (unset) Extra raw QEMU arguments (escape hatch)

5. Working with Disks

5.1 Resize the main disk

To expand the default 64 GB disk, set DISK_SIZE:

environment:
  DISK_SIZE: "256G"

This also works on an existing installation to grow the disk without data loss.

Important

After enlarging an existing disk, the extra space appears as unallocated inside Windows. You must extend the partition manually using Windows Disk Management to actually use it. Microsoft's guide: https://learn.microsoft.com/en-us/windows-server/storage/disk-management/extend-a-basic-volume.

5.2 Add extra disks

Attach additional virtual disks by declaring their size and a matching /storageN volume:

environment:
  DISK2_SIZE: "32G"
  DISK3_SIZE: "64G"
volumes:
  - ./example2:/storage2
  - ./example3:/storage3

5.3 Pass through a physical disk

You can hand a real host disk or partition directly to Windows:

devices:
  - /dev/sdb:/disk1
  - /dev/sdc1:/disk2
  • /disk1 becomes the main drive and is formatted during installation.
  • /disk2 and higher are added as secondary drives and are left untouched.

Caution

The /disk1 device is wiped and formatted by Windows Setup. Never map a disk containing data you care about to /disk1.


6. Sharing Files With the Host

After installation a folder named Shared appears on the Windows desktop. Use it to exchange files with the host machine. To point it at a specific host folder, bind that folder to /shared:

volumes:
  - ./example:/shared

The contents of ./example then appear in the Shared folder inside Windows.

Note

The shared folder is provided over Samba (SMB) from the container. You can mount additional shares at /shared2 and /shared3 as well; they appear as Data2 and Data3.


7. Manual Installation

The automatic installer applies many settings that prevent common problems when Windows runs in a virtual environment, so it is strongly recommended. If you nonetheless want to click through Windows Setup yourself:

environment:
  MANUAL: "Y"

Warning

With MANUAL: "Y" you are responsible for partitioning, account creation, and driver selection. For Windows 11, the container automatically enables Secure Boot and a TPM so Setup's hardware checks pass — but you still drive the wizard manually through the web viewer.


8. Networking

By default the container uses bridge networking and shares the host's IP address. Ports 8006 (web viewer) and 3389 (RDP) are published to the host. For most users this is all that's needed.

8.1 Give the container its own IP (macvlan)

To make the container appear as a separate device on your LAN, create a macvlan network:

docker network create -d macvlan \
    --subnet=192.168.0.0/24 \
    --gateway=192.168.0.1 \
    --ip-range=192.168.0.100/28 \
    -o parent=eth0 vlan

Adjust the addresses to match your network, then attach the container:

services:
  windows:
    container_name: windows
    # ...
    networks:
      vlan:
        ipv4_address: 192.168.0.100

networks:
  vlan:
    external: true

With macvlan, all ports are exposed automatically, so you no longer need the ports: mapping.

Important

Because of how macvlan works, the Docker host itself cannot reach the container's macvlan IP. If host-to-container access matters, create a second macvlan bridge as a workaround.

8.2 Let Windows get an IP from your router (DHCP)

After setting up macvlan, you can have Windows itself request an address from your router — so the container and Windows each have their own LAN IP:

environment:
  DHCP: "Y"
devices:
  - /dev/vhost-net
device_cgroup_rules:
  - 'c *:* rwm'

9. Connecting to Windows

There are two ways to reach the running machine.

9.1 Web viewer (port 8006)

Open http://127.0.0.1:8006/ in any browser. This viewer is intended mainly for watching the installation and for quick access. Its picture quality is reduced and it has no audio and no clipboard.

9.2 Remote Desktop / RDP (port 3389)

For day-to-day use, connect with any Microsoft Remote Desktop client to the container's IP using username Docker and password admin (or your configured credentials). RDP gives you full resolution, audio, and clipboard.

Platform RDP client
Windows Type mstsc in the search box
macOS / iOS Microsoft Remote Desktop (App Store)
Android Microsoft Remote Desktop (Play Store)
Linux FreeRDP

Tip

If RDP refuses to connect even though Windows is running, your host may require the additional NET_RAW capability. Add - NET_RAW under cap_add alongside NET_ADMIN.


10. Advanced Usage

10.1 Verify that your system supports KVM

On a Linux host:

sudo apt install cpu-checker
sudo kvm-ok
INFO: /dev/kvm exists
KVM acceleration can be used

If kvm-ok reports that KVM cannot be used, check that:

  • Virtualization extensions (Intel VT-x or AMD SVM) are enabled in your BIOS/UEFI.
  • Nested virtualization is enabled if the container runs inside another VM.
  • You are not on a cloud VPS that blocks nested virtualization.

If kvm-ok succeeds but the container still reports a missing KVM device, add privileged: true to your compose file (or sudo to your docker command) to rule out a permission issue.

10.2 Install a custom ISO

Point VERSION at any ISO URL to download an unsupported image:

environment:
  VERSION: "https://example.com/win.iso"

Or skip downloading entirely and bind a local ISO file:

volumes:
  - ./example.iso:/boot.iso

When you bind /boot.iso, the VERSION value is ignored.

10.3 Run a script after installation

Place an install.bat (plus any files it needs) in a folder and bind it to /oem:

volumes:
  - ./example:/oem

The folder is copied to C:\OEM inside Windows, and install.bat runs automatically as the final step of installation — ideal for unattended software setup.

10.4 Pass through a USB device

Find the device's vendor and product IDs with lsusb, then:

environment:
  ARGUMENTS: "-device usb-host,vendorid=0x1234,productid=0x1234"
devices:
  - /dev/bus/usb

Warning

Do not attach a USB mass-storage device before Windows Setup has finished. Doing so can fail the install, or worse, the drive may be formatted as the system disk and its data lost. Keep USB storage disconnected on first launch.

10.5 Stopping the container gracefully

The compose example sets stop_grace_period: 2m (and the CLI uses --stop-timeout 120). This gives Windows time to perform a clean ACPI shutdown when you run docker compose down or docker stop. Keep this generous timeout so Windows is not forcibly killed mid-write.

❯ Received SIGTERM, sending ACPI shutdown signal...
❯ Waiting for Windows to shut down... (3/110)
❯ Shutdown completed!

11. Troubleshooting

The format below lists the message or symptom, its cause, and the fix.

Symptom: pull access denied when starting the container

Cause: The image name is dockurr/windows — note the double "r" in dockurr. Using dockur/windows (the GitHub org name) as the image name fails. Solution: Use image: dockurr/windows exactly. Prevention: Copy the image name directly from the Quick Start compose file.

Symptom: Container exits immediately / complains about a missing KVM device

Cause: The host lacks KVM acceleration, or the container cannot access /dev/kvm. Solution: Run sudo kvm-ok (Section 10.1). Enable VT-x/SVM in BIOS, enable nested virtualization if inside a VM, or add privileged: true to rule out permissions. Prevention: Verify KVM support before deploying.

Symptom: RDP will not connect though the web viewer works

Cause: On some hosts RDP requires the NET_RAW capability in addition to NET_ADMIN. Solution: Add - NET_RAW under cap_add. Prevention: Include both capabilities when you intend to use RDP.

Symptom: BdsDxe: failed to load Boot0002 ... Not Found appears in the logs

Cause: This is a harmless UEFI firmware message printed before the boot device is selected. The container already filters it from the viewer, but it can surface in raw container logs. Solution: No action needed if Windows then boots. The installation continues normally. Prevention: Not applicable — the message is cosmetic.

Symptom: Error: VERSION ... setup has failed to validate the product key

Cause: Some trimmed community images (for example tiny11) ship without a valid embedded product key, so Setup's key validation fails. Solution: Use one of the standard VERSION values from Section 3, or supply a valid key via the KEY variable. Prevention: Prefer the official editions for unattended installs.

Symptom: Shared folder shows file-synchronization errors

Cause: The host bind-mounted folder has restrictive permissions or, on SELinux systems, the wrong security label. Solution: Ensure the host folder is writable. On SELinux hosts, add the :Z flag to the bind mount, e.g. - ./example:/shared:Z. Prevention: Create the shared folder with appropriate ownership before first start.

Symptom: The account is locked and you cannot log in

Cause: Repeated failed logons (often via exposed RDP) can trigger the Windows account-lockout policy. Solution: Wait for the lockout to expire, or reset the policy from inside Windows. Avoid exposing port 3389 to the public internet. Prevention: Keep RDP on a private network; use a strong PASSWORD.

Symptom: Host (especially a laptop) overheats during installation

Cause: The install phase is CPU-intensive and uses all assigned cores. Solution: Lower CPU_CORES so the host retains thermal headroom. Prevention: Assign fewer cores than the host has, particularly on laptops.

Symptom: Windows hangs on a spinning startup circle (nested in ESXi/another hypervisor)

Cause: Nested virtualization is not fully enabled on the outer hypervisor. Solution: Enable nested virtualization (and "expose hardware-assisted virtualization") on the outer VM, then restart. Prevention: Confirm kvm-ok passes inside the outer VM first.

Symptom: Network drops with a passt/SIGABRT crash

Cause: A known incompatibility between the passt user-mode networking backend and certain CPUs. Solution: Switch to bridge or macvlan networking (Section 8). Prevention: Use bridge networking unless you specifically need user-mode networking.


12. FAQ

Q: Do I need a Windows license or product key? A user account and a trial/generic key are configured automatically so installation completes without prompting. For production or activated use, supply your own license and the KEY variable. Any keys present in the project are generic placeholders published by Microsoft for trial purposes.

Q: Is this project legal? Yes. The project contains only open-source code and distributes no copyrighted material — the Windows media is downloaded at runtime directly from Microsoft's own servers (or public mirrors). The product names and logos are trademarks of their respective holders; the project is not affiliated with or endorsed by Microsoft.

Q: Where does the Windows image come from? On first run, the container downloads the official ISO/ESD from Microsoft's servers. If those are unreachable, it falls back to public mirror hosts. You can also supply your own ISO (Section 10.2).

Q: Will my installation survive a container restart or recreation? Yes, as long as /storage is bound to a host folder or named volume. The disk image and all settings are kept there.

Q: Can I run multiple Windows containers at once? Yes. Give each its own container_name, its own /storage folder, and distinct published host ports (e.g. 8007:8006).

Q: How do I get higher graphics quality, audio, or clipboard? Connect over RDP (Section 9.2) rather than the web viewer.

Q: Can I run macOS or Linux this way instead? Yes — use dockur/macos for macOS or qemus/qemu for a Linux desktop. They share much of the same machinery.

Q: How do I run ARM64 Windows? Use dockur/windows-arm. This dockur/windows image is for x64 hosts and x64 Windows.

Q: The installation finished — can I delete the downloaded ISO? The container removes the installation ISO automatically once setup completes (unless you set REMOVE: "N"), so you don't need to manage it.