Cách chạy Windows trên Docker (Contaner/Kubernetes)

Trong thực tế các doanh nghiệp yêu cầu bảo mật cao, có nhóm nhân sự không được phép kết nối internet trực tiếp, vậy lúc này làm sao khi nhân sự muốn làm tác vụ cần internet? Những giải pháp cấp thiết bị sẽ là bài toán đáng cân nhắc, thay vậy việc sử dụng Docker để tạo nhanh chóng một máy ảo Windows và truy cập trực tiếp bằng private IP của doanh nghiệp là điều hợp lý.

Hay có team QA nhờ bạn spin up nhanh một Windows Server 2022 để test automation và task chỉ cần một môi trường Windows để dùng vài tiếng, mà nhiều khi bạn phải đánh đổi hàng giờ cài đặt, hàng chục GB ổ cứng, hoặc chi phí sử dụng VPS/Cloud.

Hoặc đơn giản hơn, nếu bạn đã từng muốn có ngay một chiếc Windows để test App, chạy thử phần mềm, dựng lab học, hoặc demo cho khách… nhưng rồi bị mất thời gian như tải ISO, Setup, chờ đợi,… và trong đầu nảy ra suy nghĩ giờ mà có one-click hay gõ vài command là sẽ có ngay hạ tầng nhỉ?

Thì chính xác giải pháp ở bài này là điều rất đáng để bạn quan tâm.

6ced212d-1ea2-4dfe-82d2-fcc3fc123993

Lợi ích khi sử dụng Windows trên Docker

  1. Triển khai cực nhanh – chỉ cần một vài setup ban đầu và lệnh Docker là có ngay môi trường Windows, không mất hàng giờ cài đặt như VM.
  2. Tự động hóa dễ dàng – có thể tích hợp vào CI/CD, pipeline, script để spin up/xóa Windows bất kỳ lúc nào.
  3. Tiết kiệm tài nguyên – nhẹ hơn máy ảo truyền thống, không “ăn” RAM/CPU quá nhiều.
  4. Khởi tạo lại dễ dàng – môi trường có thể tạo – xóa – tạo lại nhiều lần mà không để lại “rác”.
  5. Đa dạng version – chạy song song Windows 7, 10, 11, Windows Server… chỉ bằng việc đổi VERSION.
  6. Tiết kiệm chi phí – không cần thuê VPS hay cloud đắt đỏ, chạy ngay trên máy hoặc hạ tầng có sẵn.
  7. Chia sẻ dễ dàng – bind volume để chia sẻ file giữa host ↔ Windows chỉ trong vài giây.
  8. Linh hoạt trong bảo mật – phù hợp với doanh nghiệp hạn chế truy cập internet, có thể dựng sẵn image nội bộ cho nhân sự sử dụng.
  9. Truy cập tiện lợi – dùng web viewer để theo dõi cài đặt, hoặc RDP full trải nghiệm như PC thật.
  10. Phù hợp nhiều đối tượng – DevOps, QA, tester, sinh viên, security team, tất cả đều có thể tận dụng.

Với rất nhiều ưu điểm khác. Tuy nhiên, chắc chắn không có cái gì gọi là hoàn hảo hoàn toàn sẽ tùy thuộc việc hiểu bản chất của công cụ và bài toán để ứng dụng phù hợp.

Các bước cài đặt Windows trên Docker

Step 1: Chuẩn bị

Tùy vào hạ tầng và bài toán của bạn để có hạ tầng phù hợp, dưới đây là cấu hình đề xuất nếu như bạn muốn làm Lab để nắm bắt được kiến thức, server Ubuntu được cài trên VMware với phần cứng máy chủ cần hỗ trợ công nghệ ảo hóa (Virtualization).

Hệ điều hành RAM CPU Dung lượng lưu trữ
Ubuntu Server 8 GB 4 Core 40 GB

Server đã được cài đặt Docker và Docker Compose phiên bản không quá cũ, bạn có thể tham khảo bài viết Cách cài đặt Docker phiên bản mới nhất tự động bằng bashscript để có thể cài đặt nhanh chóng phiên bản mới nhất bằng 1 câu lệnh với bashscript.

Step 2: Bật Nested VT-x/EPT trên VMware

Bước 1. Đảm bảo đã tắt VM

Bước 2: Cấu hình bật Nested VT-x/EPT

  • vSphere/ESXi:

    • Chuột phải VM → Edit Settings → VM OptionsAdvancedConfiguration Parameters…
    • Thêm (hoặc sửa) khóa: vhv.enable = "TRUE"
    • CPU: bảo đảm “Hardware virtualization” được bật (Expose hardware assisted virtualization to the guest OS). Với UI mới: CPU → Advanced → tick “Expose virtualization extensions to the guest OS”.
    • Nếu có mục CPU/MMU Virtualization, chọn “Intel VT-x/EPT”.
  • VMware Workstation / Fusion:

    • Chuột phải VM → Settings → Processors → Chọn “Virtualize Intel VT-x/EPT or AMD-V/RVI”.
    • (Tuỳ chọn) Chọn “Virtualize CPU performance counters”.
1b21d51c-d37d-44ad-bb3f-53b8a3e2d7b2

Bước 3: Bật lại VM, kiểm tra guest đã thấy VT-x

grep -m1 -o 'vmx' /proc/cpuinfo || echo "NO_VMX"

kết quả chính xác vmx.

Step 3: Cài gói và bật module KVM/TUN

sudo apt update

sudo apt install -y qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils \
  linux-modules-extra-$(uname -r)

sudo modprobe kvm
sudo modprobe tun

lsmod | grep -E 'kvm|kvm_intel|tun'
ls -l /dev/kvm /dev/net/tun

Kết quả chính xác:

devopsvietnamresearch@devopsvietnam-lab:~# lsmod | grep -E 'kvm|kvm_intel|tun'
kvm_intel             487424  0
kvm                  1409024  1 kvm_intel
irqbypass              12288  1 kvm

devopsvietnamresearch@devopsvietnam-lab:~# ls -l /dev/kvm /dev/net/tun
crw-rw---- 1 root kvm  10, 232 Sep  1 09:27 /dev/kvm
crw-rw-rw- 1 root root 10, 200 Sep  1 09:27 /dev/net/tun

Trong trường hợp nếu /dev/net/tun chưa có:

sudo mkdir -p /dev/net
sudo mknod /dev/net/tun c 10 200
sudo chmod 0666 /dev/net/tun

Step 4: Cấp quyền truy cập (để tránh “Permission denied”)

Đảm bảo nhóm kvm có quyền và Docker root có thể dùng được

sudo chgrp kvm /dev/kvm
sudo chmod 660 /dev/kvm

(Tùy chọn) nếu bạn chạy Docker rootless hay user khác:

sudo setfacl -m u:root:rw,g:kvm:rw /dev/kvm

Step 5: Cài đặt Window trên Docker

1. Dùng Docker CLI

docker run -d --name windows \
  --privileged \
  --security-opt apparmor=unconfined \
  --security-opt seccomp=unconfined \
  --device=/dev/kvm --device=/dev/net/tun \
  --cap-add=NET_ADMIN \
  -p 8006:8006 -p 3389:3389/tcp -p 3389:3389/udp \
  -v $PWD/windows:/storage \
  -e VERSION=11 -e CPU_CORES=4 -e RAM_SIZE=6G -e DISK_SIZE=20G \
  dockurr/windows

2. Dùng Docker Compose

services:
  windows:
    image: dockurr/windows
    container_name: windows
    privileged: true
    security_opt:
      - apparmor=unconfined
      - seccomp=unconfined
    cap_add:
      - NET_ADMIN
    devices:
      - /dev/kvm
      - /dev/net/tun
    ports:
      - "8006:8006"
      - "3389:3389/tcp"
      - "3389:3389/udp"
    volumes:
      - ./windows:/storage
    environment:
      VERSION: "11"
      CPU_CORES: "4"
      RAM_SIZE: "6G"
      DISK_SIZE: "20G"
    restart: always
    stop_grace_period: 2m

Khởi chạy Windows trên docker

docker compose up -d

Kiểm tra logs sẽ thấy kết quả như sau:

docker logs -f windows
f65a90ef-2adb-4d0b-a328-f808d5728f1c

Truy cập trên trình duyệt với địa chỉ http://IP_SERVER:8006 sẽ thấy windows trên docker đang được khởi tạo

b5731dcb-f958-4062-9d58-b89b97b7f4b3

Khởi tạo thành công Windows chạy trên Docker đã chính thức hoạt động

60e31935-e954-416e-a8a9-b663961b1044

(Tùy chọn) Bạn có thể setting để thiết lập lại kích thước màn hình để xem rõ nét hơn

7ac55103-e473-4a64-88d2-0ee72cc31b21

Bây giờ bạn hoàn toàn có thể truy cập internet và sử dụng tùy mục đích

e3294ebd-1317-4ae4-913d-fee4c87dd960

Step 6: Các tùy chỉnh cấu hình và mở rộng

Cách thay đổi phiên bản Windows trên Docker

Thêm biến môi trường VERSION trong docker-compose.yml:

environment:
  VERSION: "11"
Giá trị Phiên bản Windows Dung lượng ISO
11 Windows 11 Pro 5.4 GB
11l Windows 11 LTSC 4.7 GB
11e Windows 11 Enterprise 4.0 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 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

Cách thay đổi nguồn ISO

Trong doanh nghiệp thường sẽ ưu tiên sử dụng các nguồn từ nội bộ cung cấp để đảm bảo sự tối ưu và bảo mật nên bạn có thể tham khảo 2 cách dưới đây để dùng nguồn ISO khác.

1. Sử dụng link đến ISO

Trong VERSION thay vì chỉ định như trên bạn có thể sử dụng trực tiếp link đến file ISO, link này có thể là ISO được upload lên nền tảng lưu trữ nội bộ, dưới đây là ví dụ cụ thể cách sử dụng:

services:
  windows:
    image: dockurr/windows
    container_name: windows
    privileged: true
    security_opt:
      - apparmor=unconfined
      - seccomp=unconfined
    cap_add:
      - NET_ADMIN
    devices:
      - /dev/kvm
      - /dev/net/tun
    ports:
      - "8006:8006"
      - "3389:3389/tcp"
      - "3389:3389/udp"
    volumes:
      - ./windows:/storage
    environment:
      VERSION: "https://archive.org/download/win-server-2012R2-eva-multi-lang/9600.17050.WINBLUE_REFRESH.140317-1640_X64FRE_SERVER_EVAL_EN-US-IR3_SSS_X64FREE_EN-US_DV9.ISO"
      CPU_CORES: "4"
      RAM_SIZE: "6G"
      DISK_SIZE: "20G"
    restart: always
    stop_grace_period: 2m

Kết quả tương tự sẽ thấy ở màn hình khởi tạo ISO được download

62e747a8-4ae7-4b98-ad22-5594c90fabf8

2. Mount bằng file ISO vào container

Thay vì đặt URL trong biến VERSION, bạn sẽ bind-mount ISO vào container. Docker image dockur/windows mặc định sẽ tự ưu tiên file /boot.iso nếu nó tồn tại, do đó ta chỉ cần bind đường dẫn ISO vào đúng vị trí đó và lúc này sẽ không sử dụng ENV VERSION như sau:

services:
  windows:
    image: dockurr/windows
    container_name: windows
    privileged: true
    security_opt:
      - apparmor=unconfined
      - seccomp=unconfined
    cap_add:
      - NET_ADMIN
    devices:
      - /dev/kvm
      - /dev/net/tun
    ports:
      - "8006:8006"
      - "3389:3389/tcp"
      - "3389:3389/udp"
    volumes:
      - ./windows:/storage
      - /home/devopsvietnamresearch/iso/en_windows_server_2012_r2.iso:/boot.iso
    environment:
      CPU_CORES: "4"
      RAM_SIZE: "6G"
      DISK_SIZE: "20G"
    restart: always
    stop_grace_period: 2m

Cách thay đổi dung lượng Disk

Thêm biến DISK_SIZE:

environment:
  DISK_SIZE: "20G"

Cách chia sẻ file với máy host

Trong window, mở File Explorer → Network → click vào host.lan. Trong docker-compose.yml:

volumes:
  - ./example:/data

Folder ./example trên host sẽ xuất hiện trong Windows tại \\host.lan\Data.

Cách cấu hình CPU & RAM

Mặc định: 2 CPU & 4GB RAM. Để thay đổi:

environment:
  RAM_SIZE: "6G"
  CPU_CORES: "4"

Cách đặt tên người dùng và mật khẩu

environment:
  USERNAME: "devopsvietnam"
  PASSWORD: "research"

Mặc định: Docker / admin.

Cách chọn ngôn ngữ Windows

environment:
  LANGUAGE: "Vietnamese"

Hiện tại Windows trên docker hỗ trợ nhiều ngôn ngữ: English, Chinese, Japanese, Korean, French, German, Russian, Spanish, Portuguese, Thai, Turkish, Vietnamese,…

Cách để thực hiện cài đặt thủ công

Khuyến nghị bạn nên sử dụng chế độ cài đặt tự động vì nó sẽ tự cấu hình nhiều thiết lập giúp tránh lỗi phổ biến khi chạy Windows trong môi trường ảo hóa.

Tuy nhiên, nếu bạn vẫn muốn tự cài đặt thủ công và chấp nhận rủi ro, hãy thêm biến môi trường sau vào file docker-compose.yml:

environment:
  MANUAL: "Y"

Cách kết nối bằng RDP

Trình web viewer chỉ nên dùng trong quá trình cài đặt vì chất lượng hình ảnh thấp, không hỗ trợ âm thanhkhông hỗ trợ copy/paste.

Để có trải nghiệm tốt hơn, hãy sử dụng Remote Desktop (RDP) của Microsoft để kết nối trực tiếp đến IP của container bằng thông tin đăng nhập mặc định:

  • Username: Docker
  • Password: admin

Các lựa chọn client RDP:

ef903500-cf85-4dde-bf52-a04519ed62f9

Cách gán địa chỉ IP cho container

Mặc định, container Windows sử dụng bridge network, tức là dùng chung IP với host. Nếu bạn muốn cấp riêng một địa chỉ IP cho container, hãy tạo mạng macvlan như sau:

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

Lưu ý: Hãy điều chỉnh subnet, gatewayparent cho phù hợp với mạng nội bộ của bạn.

Sau khi tạo network, sửa file docker-compose.yml như sau:

services:
  windows:
    container_name: windows
    ..
<snip>..
    networks:
      vlan:
        ipv4_address: 192.168.0.100

networks:
  vlan:
    external: true

Ưu điểm: Khi dùng macvlan, bạn không cần mở port thủ công nữa, vì container sẽ được cấp IP riêng biệt.

Quan trọng: Theo thiết kế của macvlan, Docker host không thể giao tiếp trực tiếp với container qua IP đó. Nếu cần, bạn phải cấu hình macvlan thứ hai để khắc phục.

Cách để Windows tự nhận IP từ router

Sau khi cấu hình macvlan, bạn có thể để Windows nhận IP động từ router/DHCP server, giống như một máy tính thật.

Thêm các dòng sau vào docker-compose.yml:

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

Cách thêm nhiều ổ đĩa

Để tạo thêm các ổ đĩa bổ sung, sửa docker-compose.yml như sau:

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

Cách gắn ổ đĩa vật lý vào container

Bạn có thể pass-through ổ đĩa vật lý hoặc phân vùng trực tiếp cho container bằng cách thêm vào docker-compose.yml:

devices:
  - /dev/sdb:/disk1
  - /dev/sdc1:/disk2
  • Dùng /disk1 nếu muốn nó trở thành ổ đĩa chính (sẽ bị format khi cài đặt).
  • Dùng /disk2 trở đi nếu muốn gắn thêm ổ phụ (không bị format).

Cách gắn USB vào container

Để pass-through một thiết bị USB:

  1. Dùng lệnh lsusb để lấy vendor IDproduct ID của thiết bị.
  2. Thêm các thông tin này vào file docker-compose.yml:
environment:
  ARGUMENTS: "-device usb-host,vendorid=0x1234,productid=0x1234"
devices:
  - /dev/bus/usb

Lưu ý: Nếu USB là ổ đĩa ngoài, hãy kết nối sau khi quá trình cài đặt Windows hoàn tất. Nếu cắm trước, thứ tự ổ đĩa có thể bị thay đổi, gây lỗi khi cài.

Cách kiểm tra hệ thống có hỗ trợ KVM không

sudo apt install cpu-checker
sudo kvm-ok

Nếu không hỗ trợ, hãy bật Intel VT-x hoặc AMD SVM trong BIOS.

Cách chạy Windows trên Kubernetes

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

Với Docker, việc triển khai Windows không còn là một quá trình phức tạp và tốn thời gian nữa. Chỉ với một vài dòng lệnh, bạn có thể tạo ra môi trường Windows hoàn chỉnh, linh hoạt và dễ dàng tùy chỉnh theo nhu cầu. Từ developer cần test nhanh ứng dụng, QA muốn kiểm thử đa phiên bản, đến DevOps cần tích hợp Windows vào pipeline, tất cả đều có thể tận dụng giải pháp này để tiết kiệm thời gian, giảm chi phí và tối ưu tài nguyên. Đây không chỉ là cách cài Windows nhanh hơn, mà còn là một bước tiến để bạn làm việc hiệu quả và chủ động hơn trong mọi tình huống.

Chia sẻ bài viết:
Theo dõi
Thông báo của
2 Góp ý
Được bỏ phiếu nhiều nhất
Mới nhất Cũ nhất
Phản hồi nội tuyến
Xem tất cả bình luận