Yankun Yang

Running Windows Apps on Linux with Docker: A Complete Guide

This post is written with the assistance of Claude Sonnet 4.5 (Anthropic).


How I got a Windows-only music app running on Ubuntu 24.04 — with audio — using dockur/windows.


Background

I wanted to use Qishui Music (汽水音乐), a music streaming app from ByteDance that only has official clients for Windows, macOS, Android, and iOS. No Linux support. After looking at a few options — the web app, Wine, Waydroid — I ended up going down a more interesting path: running a full Windows VM inside a Docker container using dockur/windows.


How dockur/windows Works

Despite the name, this isn't a true Windows container. It's a QEMU/KVM virtual machine wrapped inside a Docker container. The container shell passes through /dev/kvm to get near-native performance via hardware virtualization. You get:

The architecture looks roughly like this:

Windows VM (QEMU)
    ↕ QEMU user-mode NAT
Docker container (dockurr/windows image)
    ↕ /dev/kvm passthrough
Linux host (Ubuntu 24.04 + KVM)

Choosing a Windows Version

dockur/windows supports everything from Windows 2000 to Windows Server 2025. For running a lightweight app like a music player, I went with Windows 10 LTSC 2021 (VERSION: "10l"):

LTSC removes preinstalled apps but keeps all core system components, fonts, and runtime libraries intact — Office installs fine, for example.


The docker-compose.yml

services:
  windows:
    image: dockurr/windows
    container_name: windows
    environment:
      VERSION: "10l"
      LANGUAGE: "Chinese"
      KEYBOARD: "zh-CN"
      REGION: "zh-CN"
      RAM_SIZE: "8G"
      CPU_CORES: "4"
      DISK_SIZE: "128G"
      USERNAME: "myuser"
      PASSWORD: "mypassword"
    devices:
      - /dev/kvm
      - /dev/net/tun
    cap_add:
      - NET_ADMIN
    ports:
      - "8006:8006"
      - "3389:3389/tcp"
      - "3389:3389/udp"
    volumes:
      - ./windows:/storage
      - ./shared:/shared
    restart: unless-stopped
    stop_grace_period: 2m

A few notes on the config:

Starting it

docker compose up -d

Then open http://localhost:8006 in your browser and watch the automated installation complete. No interaction needed.


Getting the ISO Locally (When Download Fails)

The container downloads the Windows ISO automatically, but this can fail depending on your network. The cleanest workaround is to download the ISO yourself and mount it directly:

volumes:
  - ./windows:/storage
  - ./Win10_LTSC_2021.iso:/boot.iso  # container uses this instead of downloading

When /boot.iso is present, the container skips the download entirely. The official Microsoft site doesn't offer LTSC directly — massgrave.dev is a well-known community resource for genuine Microsoft ISOs.


Connecting via RDP

The web viewer at port 8006 is only meant for the installation phase — low image quality, no audio, no clipboard. For actual use, connect via RDP.

On Linux, use FreeRDP:

sudo apt install freerdp2-x11

xfreerdp /v:localhost:3389 \
  /u:myuser /p:mypassword \
  /cert:ignore \
  /sound:sys:pulse \
  /audio-mode:0

This streams the Windows desktop to your local display and routes audio back through PulseAudio.


Getting Audio Working

This took some debugging. The RDP audio pipeline works fine — you can hear system sounds — but Qishui Music was completely silent. Nothing showed up in Windows' volume mixer during playback.

The fix turned out to be embarrassingly simple: run the app as Administrator.

Right-click the app → Properties → Compatibility → check "Run this program as an administrator".

My best guess: the app uses WASAPI in exclusive mode, which requires elevated privileges to access the virtual audio device in a VM environment. On real hardware this works fine; in a QEMU VM it silently fails without admin rights.


Networking Notes

The VM's network goes through QEMU's user-mode NAT — Windows gets an IP like 172.30.0.1 as its gateway, which is entirely virtual and doesn't map directly to anything on the host. This makes proxy configuration non-trivial.

The simplest solution: install a proxy client directly inside Windows and import your subscription/config via the SMB share (\\host.lan\Data). Trying to forward the host's proxy into the VM adds unnecessary complexity.


Auto-start on Boot

With restart: unless-stopped in the compose file, the container starts automatically with the Docker daemon. Make sure Docker itself is enabled at boot:

sudo systemctl enable docker

Resource Usage

On my machine (AMD Ryzen 9600X, 32 GB RAM), with 4 cores and 8 GB allocated to the VM:

CPU: ~126%  (≈1.3 cores out of 4 allocated — very light)
MEM: 8.1 GiB / 31 GiB (26%)

Completely comfortable. The VM idles quietly in the background.


Summary

Step Solution
Run Windows on Linux dockur/windows (QEMU/KVM in Docker)
Windows version Windows 10 LTSC 2021
ISO download failed Mount local ISO as /boot.iso
Remote desktop FreeRDP with /sound:sys:pulse
No audio in music app Run app as Administrator
Proxy inside VM Install proxy client natively in Windows
Auto-start restart: unless-stopped + systemctl enable docker

The whole setup took a few hours of troubleshooting, but the end result is stable: a persistent Windows environment running as a background service, accessible via RDP with audio, using about 26% of system RAM.


Tested on Ubuntu 24.04, AMD Ryzen 9600X, NVIDIA RTX 5060 Ti, 32 GB RAM.