Windows Subsystem for Linux

There are some instances when you need a Windows instance, but you don't need a full VM to do it. You can use a Docker Container for Windows XP – Windows 11 or one of the Windows Severs. Yes, this is possible, and it's a usable system.

Share
Windows Subsystem for Linux
Photo by Clint Patterson / Unsplash

How to do it? Set up Docker with Dockge in a VM and create the files: compose.yaml and .env and a macvlan for making it a full member of your LAN.
Then start the container and the installation process will run fully automatic. Once you have the desktop in the browser on http://<IP>:8006 (VM IP or the local IP of Windows) your Windows installation is ready to be configured and updated (if still permitted) and then, if you like/need to, activate it.

Features

  • ISO downloader is included
  • Automatic installation
  • KVM acceleration is needed
  • Web-based viewer, noVNC or RDP
  • Local network IP for the Windows instance

We need KVM acceleration

  • 👉 You need to use the CPU type Host
  • ✋ you can't use a QEMU CPU type
  • To get a virtual CPU using KVM acceleration, ensure that your host's CPU supports virtualization (VT-x for Intel or AMD-V for AMD) and that virtualization is enabled in the BIOS.
    Then, you can create a virtual machine and configure it to use KVM by selecting the appropriate CPU type, such as "host" or "kvm64."

Other Notes

By default, you can access the Windows container with noVNC, but for better performance use RDP. And for a private IP, you need to set up and use a macvlan

⚠️
Remember security: for Windows especially, but for Docker and the VM too

The VM

Set up a VM

As windows needs a 64 G disk and docker also needs some, you need to make the disk big. Remember, this isn't a server, it's a super bloated desktop. Tested with 2 cores, 8 G RAM and 70 G disk. It will run, but it's slow. Give it more, much more. For the VM, I used Ubuntu 24.04 LTS mini. Using the whole disk, no LVM.

Update the VM

sudo apt update && sudo apt upgrade -y

Install Docker-CE

Download the GPG key

sudo wget -qO /etc/apt/keyrings/docker.asc https://download.docker.com/linux/ubuntu/gpg

Download GPG key and add to a specified directory:

Add the repository

echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(lsb_release -sc) stable" | sudo tee /etc/apt/sources.list.d/docker.list

Add the Docker CE repository:

Install Docker-CE

sudo apt update
sudo apt install -y docker-ce

Installing Docker installs the Docker service daemon, but also: containerd.io, docker-buildx-plugin, docker-ce-cli, docker-ce-rootless-extras, docker-compose-plugin.

Option

Add current user to docker group
  • By default, root and user with sudo privileges can use Docker.
  • During installation, a group docker is created. So, if you want to allow using Docker for non-root users, you can add the user to the docker group.
  • This will elevate a normal user's privileges. Remember the security aspect of doing it.
sudo usermod -a -G docker $USER

If you understand and accept the security issues, you might like to do this

Initial Testing

To make changes to take effect, logout and login to your machine. After you're reconnected, check Docker version:

docker version

We can use the following command to determine if Docker service is running:

sudo service docker status

We can also stop, start and restart the Docker service:

sudo service docker stop
sudo service docker start
sudo service docker restart

Testing Docker

To test that Docker successfully installed, you can run the hello-world image.

docker run hello-world

The command downloads a test image, runs it in a container, prints a message, and exits.

Installing Docker installs the Docker service daemon, but also: containerd.io, docker-buildx-plugin, docker-ce-cli, docker-ce-rootless-extras, docker-compose-plugin.

Check if Docker is running sudo docker ps.

Add Dockge

Run as a normal user. Add the working directory and go to it.

mkdir -p /home/$USER/docker/ && cd /home/$USER/docker

Create Dockge

sudo docker run -d -p 5001:5001 --name Dockge --restart=unless-stopped -v /var/run/docker.sock:/var/run/docker.sock -v /home/$USER/docker/dockge/data:/app/data -v /home/$USER/docker/stacks:/home/$USER/docker/stacks -e DOCKGE_STACKS_DIR=/home/$USER/docker/stacks louislam/dockge:latest
services:
  dockge:
    ports:
      - 5001:5001
    container_name: Dockge
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /home/$USER/docker/dockge/data:/app/data
      - /home/$USER/docker/stacks:/home/$USER/docker/stacks
    environment:
      - DOCKGE_STACKS_DIR=/home/$USER/docker/stacks
    image: louislam/dockge:latest
networks: {}

Check if it's running sudo docker ps.

Connect to Dockge

In your browser, connect to the VM using http://<VM IP>:5001 and set it up.

Enter your preferred username and password (min. 6 letters and numbers) to start.
You can create .env entries and networks directly in the GUI.

Now, you can start to create the stack.


Windows using Docker

Versions that are supported

Versions supported can be found below. Use the Code from below to request a version,

  • Enter it in your compose.yaml -file in the environment section as VERSION: "xp".
  • For a generic compose.yaml, you can use MANUAL: Y in the environment section.
    You then enter the appropriate code at run time.
Code Windows 11 versions Size
11 Windows 11 Pro 5.4 GB
11l Windows 11 LTSC 4.7 GB
11e Windows 11 Enterprise 4.0 GB
Code Windows 10 versions Size
10 Windows 10 Pro 5.7 GB
10l Windows 10 LTSC 4.6 GB
10e Windows 10 Enterprise 5.2 GB
Code Older Windows versions Size
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
Code Windows Servers
2025 Windows Server 2025 5.6 GB
2022 Windows Server 2022 4.7 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

The compose.yaml

We will make a Windows machine as a member of your network, you need a macvlan.

services:
  windows:
    image: dockurr/windows
    container_name: windows
    environment:
      #MANUAL: Y
      VERSION: 11
      DHCP: Y
      USERNAME: $USERNAME
      PASSWORD: $PASSWORD
      LANGUAGE: $LANGUAGE
      REGION: $REGION
      KEYBOARD: $KEYBOARD
    devices:
      - /dev/kvm
      - /dev/net/tun
      - /dev/vhost-net
    device_cgroup_rules:
      - 'c *:* rwm'
    cap_add:
      - NET_ADMIN
    ports:
      - 8006:8006
      - 3389:3389/tcp
      - 3389:3389/udp
    volumes:
      - ./windows:/storage
    networks:
      winvlan: null
    restart: unless-stopped
    stop_grace_period: 2m
networks:
  winvlan:
    external: true

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 winvlan

docker network create -d macvlan --subnet=192.168.0.0/28 --gateway=192.168.0.1 -o parent=ens1 winvlan

Create the .env -file

USERNAME: "boss"
PASSWORD: "A-strong-pA$$W0RD"

## Options ##
LANGUAGE: English
REGION:   "en-US"
KEYBOARD: "en-US"

LANGUAGE: Default is English. Use yours

Other things to Know

How to select the language

By default, the English version of Windows will be downloaded.

You can add the LANGUAGE environment variable directly to your compose.yaml file or use it from the .env -file, in order to specify an alternative language:

environment:
  LANGUAGE: "Spanish"

How to select the keyboard layout

If you want to use a keyboard layout or locale that is not the default for your selected language, you can add KEYBOARD and REGION variables directly to your compose.yaml file or use it from the .env -file, in order to specify an alternative keyboard or locale:

environment:
  REGION: "en-US"
  KEYBOARD: "en-US"
⚠️
You need to set these before starting the container:
LANGUAGEKEYBOARD and REGION

Switch to another version of Windows

By default, Windows 11 Pro will be installed. But you can add the VERSION environment variable to your compose file, in order to specify an alternative Windows version to be downloaded. The preferred way is to create a new VM.

environment:
  VERSION: "11"

You need to delete the whole installation in the /docker/stacks/windows/ directory:

  • Go to cd /docker/stacks/windows and
  • Delete the second /directory sudo -rf windows

What is the IP?

If you use DHCP, check there or click at the >_bash button and type ip a

How can Windows acquire an IP address from your router?

After configuring the container for macvlan, it is possible for Windows to become part of your home network by requesting an IP from your router, just like a real PC.

To enable this mode, in which the container and Windows will have separate IP addresses, add the following lines to your compose file:

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

How do I add multiple disks?

To create additional disks (part of the original disk), add to the compose.yaml -file

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

How to pass through a disk?

It is possible to pass-through disk devices or partitions directly by adding them to your compose file in this way:

devices:
  - /dev/sdb:/disk1
  - /dev/sdc1:/disk2

Use /disk1 if you want it to become your main drive (which will be formatted during installation), and use /disk2 and higher to add them as secondary drives (which will stay untouched).

How to pass through a USB device?

To pass through a USB device, first look up its vendor and product ID via the lsusb command, then add them to the compose.yaml -file:

environment:
  ARGUMENTS: "-device usb-host,vendorid=0x1234,productid=0x1234"
devices:
  - /dev/bus/usb
ℹ️
If the device is a USB disk drive, please wait until after the installation is fully completed before connecting it. Otherwise, the installation may fail, as the order of the disks can get rearranged.


References

The Docker Hub page [1] noVNC [2] FreeRDP [3]


  1. dockurr/windows homepage, getting started GitHub ↩︎

  2. noVNC homepage, and on GitHub ↩︎

  3. FreeRDP: A Remote Desktop Protocol Implementation. FreeRDP is a free implementation of the Remote Desktop Protocol (RDP), released under the Apache license. Enjoy the freedom of using your software wherever you want, the way you want it, in a world where interoperability can finally liberate your computing experience. homepage, GitHub, Downloads, Wiki ↩︎