├── .env ├── .github ├── pull_request_template.md └── workflows │ └── ci.yml ├── images └── screen-1.png ├── docker-compose.yml ├── startup.sh ├── docker-compose.override.yml ├── LICENSE ├── Dockerfile ├── Vagrantfile └── README.md /.env: -------------------------------------------------------------------------------- 1 | # Vagrant image settings 2 | MEMORY=8000 # 8GB 3 | CPU=4 4 | DISK_SIZE=100 -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # Current Behaviour 2 | 3 | # Expected Behaviour -------------------------------------------------------------------------------- /images/screen-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vaggeliskls/windows-in-docker-container/HEAD/images/screen-1.png -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | win10: 3 | image: docker.io/vaggeliskls/windows-in-docker-container:latest 4 | platform: linux/amd64 5 | build: 6 | dockerfile: ./Dockerfile 7 | context: . 8 | env_file: .env 9 | stdin_open: true 10 | tty: true 11 | privileged: true 12 | cgroup: host 13 | restart: always 14 | volumes: 15 | - ./Vagrantfile:/app/Vagrantfile 16 | # runtime: nvidia 17 | ports: 18 | - 3389:3389 19 | - 2222:2222 -------------------------------------------------------------------------------- /startup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -eou pipefail 3 | pwd 4 | # Start services 5 | [ -e /dev/kvm ] && chown root:kvm /dev/kvm 6 | # dbus-daemon --system --fork 7 | libvirtd --daemon 8 | virtlogd --daemon 9 | if kvm-ok 2>&1 | grep -q "KVM acceleration can NOT be used"; then 10 | export LIBVIRT_DRIVER="qemu" 11 | echo "--> KVM acceleration can NOT be used" 12 | fi 13 | # smbd --daemon 14 | # Start vagrant box 15 | # Debug: --debug 16 | vagrant up --provider=libvirt 17 | # Display running boxes 18 | virsh list --all 19 | # Keep container running 20 | exec tail -f /dev/null -------------------------------------------------------------------------------- /docker-compose.override.yml: -------------------------------------------------------------------------------- 1 | services: 2 | win10: 3 | volumes: 4 | # - /sys/fs/cgroup:/sys/fs/cgroup # Required for cgroups 5 | - libvirt_data:/var/lib/libvirt # ✅ Persist VM disk images 6 | - vagrant_data:/root/.vagrant.d # ✅ Persist Vagrant metadata 7 | - vagrant_project:/app/.vagrant # ✅ Persist Vagrant project 8 | - libvirt_config:/etc/libvirt # ✅ Persist VM configs 9 | 10 | volumes: 11 | libvirt_data: 12 | name: libvirt_data 13 | vagrant_data: 14 | name: vagrant_data 15 | vagrant_project: 16 | name: vagrant_project 17 | libvirt_config: 18 | name: libvirt_config -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 vaggeliskls 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1 2 | FROM ubuntu:24.04 3 | 4 | ENV DEBIAN_FRONTEND noninteractive 5 | ENV TERM xterm-256color 6 | 7 | RUN apt-get update -y && \ 8 | apt-get install -y \ 9 | qemu-kvm \ 10 | build-essential \ 11 | libvirt-daemon-system \ 12 | libvirt-clients \ 13 | libvirt-dev \ 14 | ebtables \ 15 | openssh-server \ 16 | curl \ 17 | net-tools \ 18 | gettext-base \ 19 | kmod \ 20 | rsync \ 21 | samba \ 22 | jq && \ 23 | apt-get autoremove -y && \ 24 | apt-get clean 25 | 26 | # Installation of vagrant 27 | ARG VAGRANT_VERSION=2.4.3 28 | ARG VAGRANT_BOX=peru/windows-server-2022-standard-x64-eval 29 | RUN wget https://releases.hashicorp.com/vagrant/${VAGRANT_VERSION}/vagrant_${VAGRANT_VERSION}-1_amd64.deb && \ 30 | apt install ./vagrant_${VAGRANT_VERSION}-1_amd64.deb && \ 31 | rm -rf ./vagrant_${VAGRANT_VERSION}-1_amd64.deb 32 | # Installtion of vagrant plugins 33 | RUN vagrant plugin install vagrant-libvirt 34 | # Installtion of vagrant box 35 | RUN vagrant box add --provider libvirt ${VAGRANT_BOX} && \ 36 | vagrant init ${VAGRANT_BOX} 37 | 38 | ENV PRIVILEGED=true 39 | ENV INTERACTIVE=true 40 | ENV VAGRANT_BOX=$VAGRANT_BOX 41 | 42 | WORKDIR /app 43 | COPY --chmod=755 startup.sh Vagrantfile /app/ 44 | 45 | ENTRYPOINT [] 46 | CMD ["/app/startup.sh"] -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Windows Vagrant VM 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | env: 8 | TAG_NAME: ${{ github.ref_name }} 9 | 10 | jobs: 11 | publish-image: 12 | runs-on: ubuntu-latest 13 | name: publish image 14 | steps: 15 | - name: Remove unnecessary files 16 | run: | 17 | sudo rm -rf /usr/share/dotnet 18 | sudo rm -rf /usr/local/lib/android 19 | sudo rm -rf "$AGENT_TOOLSDIRECTORY" 20 | sudo apt-get --ignore-missing remove -y '^aspnetcore-.*' '^dotnet-.*' '^llvm-.*' 'php.*' '^mongodb-.*' '^mysql-.*' 21 | 22 | - name: Checkout current repository 23 | uses: actions/checkout@v4 24 | 25 | - name: Docker meta 26 | id: meta 27 | uses: docker/metadata-action@v5 28 | with: 29 | # list of Docker images to use as base name for tags 30 | images: | 31 | ghcr.io/${{ github.repository }} 32 | docker.io/${{ github.repository }} 33 | # generate Docker tags based on the following events/attributes 34 | tags: | 35 | type=ref,event=branch 36 | type=ref,event=pr 37 | type=semver,pattern={{version}} 38 | type=semver,pattern={{major}}.{{minor}} 39 | # - name: Set up QEMU 40 | # uses: docker/setup-qemu-action@v3 41 | 42 | - name: Set up Docker Buildx 43 | uses: docker/setup-buildx-action@v3 44 | 45 | - name: Login to Github packages 46 | uses: docker/login-action@v3 47 | with: 48 | registry: ghcr.io 49 | username: ${{ github.actor }} 50 | password: ${{ secrets.GITHUB_TOKEN }} 51 | 52 | - name: Login to Dockerhub 53 | uses: docker/login-action@v3 54 | with: 55 | username: ${{ secrets.DOCKERHUB_REGISTRY_USERNAME }} 56 | password: ${{ secrets.DOCKERHUB_REGISTRY_PASSWORD }} 57 | 58 | - name: Build and push 59 | uses: docker/build-push-action@v6 60 | with: 61 | context: . 62 | file: Dockerfile 63 | push: true 64 | tags: ${{ steps.meta.outputs.tags }} 65 | labels: ${{ steps.meta.outputs.labels }} 66 | # platforms: linux/amd64,linux/arm64 67 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | Vagrant.configure("2") do |config| 2 | # Get values from environment variables (or set defaults) 3 | cpu_count = ENV["CPU"] ? ENV["CPU"].to_i : 4 4 | memory_size = ENV["MEMORY"] ? ENV["MEMORY"].to_i : 8000 5 | disk_size = ENV["DISK_SIZE"] ? ENV["DISK_SIZE"].to_i : 100 6 | privileged = ENV["PRIVILEGED"] ? ENV["PRIVILEGED"] == "true" : true 7 | interactive = ENV["INTERACTIVE"] ? ENV["INTERACTIVE"] == "true" : true 8 | 9 | config.vm.box = ENV["VAGRANT_BOX"] || "peru/windows-server-2022-standard-x64-eval" 10 | config.vm.box_check_update = false 11 | config.vm.network "forwarded_port", guest: 22, host: 2222, id: "ssh" # ✅ Forward SSH 12 | config.vm.network "forwarded_port", guest: 80, host: 8080, id: "http" # ✅ Forward HTTP 13 | config.vm.network "forwarded_port", guest: 443, host: 8443, id: "https" # ✅ Forward HTTPS 14 | config.vm.network "forwarded_port", guest: 3389, host: 3389, id: "rdp" # ✅ Forward RDP 15 | # Rsync 16 | # This needs the rsync to be installed on widnows box. The sync is executed before the install 17 | # that leads to: There was an error when attempting to rsync a synced folder. 18 | # config.vm.synced_folder "/app/shared", "C:/shared", type: "rsync" 19 | # Samba 20 | # Currently samba is not supported on linux hosts 21 | # https://developer.hashicorp.com/vagrant/docs/synced-folders/smb 22 | # config.vm.synced_folder "/app/shared", "C:/shared", type: "smb" 23 | # NFS 24 | # When running nfs server in container 25 | # * Not starting NFS kernel daemon: no support in current kernel 26 | config.vm.provision "shell", inline: "Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled False" 27 | config.vm.provider "libvirt" do |libvirt| 28 | libvirt.driver = ENV["LIBVIRT_DRIVER"] || "kvm" 29 | libvirt.memory = memory_size 30 | libvirt.cpus = cpu_count 31 | libvirt.machine_virtual_size = disk_size 32 | libvirt.forward_ssh_port = true 33 | end 34 | config.winrm.max_tries = 300 # default is 20 35 | config.winrm.retry_delay = 5 #seconds. This is the defaul value and just here for documentation. 36 | config.vm.provision "shell", powershell_elevated_interactive: interactive, privileged: privileged, inline: <<-SHELL 37 | # Install Chocolatey 38 | Invoke-Expression "& { $(Invoke-RestMethod 'https://aka.ms/install-powershell.ps1') } -AddToPath" 39 | Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) 40 | # Resize disk 41 | Resize-Partition -DriveLetter "C" -Size (Get-PartitionSupportedSize -DriveLetter "C").SizeMax 42 | # Enable too long paths 43 | New-ItemProperty -Path "HKLM:\\SYSTEM\\CurrentControlSet\\Control\\FileSystem" -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force 44 | SHELL 45 | end 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 💻 Windows in Docker Container 2 | 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. 3 | 4 | ⭐ **Don't forget to star the project if it helped you!** 5 | 6 | ## 📋 Prerequisites 7 | 8 | Ensure your system meets the following requirements: 9 | 10 | - **Docker:** Version 20 or higher [(Install Docker)](https://www.docker.com/) 11 | 12 | - **Host OS:** Linux 13 | 14 | - **Virtualization Enabled:** 15 | - Check with: 16 | - `grep -E -o 'vmx|svm' /proc/cpuinfo` 17 | - Output indicates: 18 | - `vmx` → Intel VT-x is supported & enabled. 19 | - `svm` → AMD-V is supported & enabled. 20 | - If virtualization is not enabled, enable it in the BIOS/UEFI settings. 21 | 22 | ## 🚀 Deployment Guide 23 | 24 | 1. Create/Update the environmental file `.env` 25 | ``` 26 | # Vagrant image settings 27 | MEMORY=8000 # 8GB 28 | CPU=4 29 | DISK_SIZE=100 30 | ``` 31 | 2. Create `docker-compose.yml` 32 | ```yaml 33 | services: 34 | win10: 35 | image: docker.io/vaggeliskls/windows-in-docker-container:latest 36 | platform: linux/amd64 37 | env_file: .env 38 | stdin_open: true 39 | tty: true 40 | privileged: true 41 | cgroup: host 42 | restart: always 43 | ports: 44 | - 3389:3389 45 | - 2222:2222 46 | ``` 47 | 4. Create `docker-compose.override.yml` when you want your VM to be persistent 48 | ```yaml 49 | services: 50 | win10: 51 | volumes: 52 | - libvirt_data:/var/lib/libvirt 53 | - vagrant_data:/root/.vagrant.d 54 | - vagrant_project:/app/.vagrant 55 | - libvirt_config:/etc/libvirt 56 | 57 | volumes: 58 | libvirt_data: 59 | name: libvirt_data 60 | vagrant_data: 61 | name: vagrant_data 62 | vagrant_project: 63 | name: vagrant_project 64 | libvirt_config: 65 | name: libvirt_config 66 | ``` 67 | 68 | 5. Run: `docker compose up -d` 69 | 70 | > When you want to destroy everything `docker compose down -v` 71 | 72 | ![windows screenshot](https://github.com/vaggeliskls/windows-in-docker-container/blob/main/images/screen-1.png?raw=true ) 73 | 74 | ## 🌐 Access 75 | 76 | ### Remote Desktop (RDP) 77 | For debugging or testing, you can connect to the VM using **Remote Desktop** on port `3389`. 78 | 79 | #### Software for Remote Desktop Access 80 | | OS | Software | 81 | |----------|----------------| 82 | | **Linux** | [`rdesktop`](https://github.com/rdesktop/rdesktop) → `rdesktop :3389` or [`Remmina`](https://remmina.org/) | 83 | | **MacOS** | [Microsoft Remote Desktop](https://apps.apple.com/us/app/microsoft-remote-desktop/id1295203466?mt=12) | 84 | | **Windows** | Built-in **Remote Desktop Connection** | 85 | 86 | --- 87 | 88 | ### SSH 89 | You can connect via SSH using either the **administrator** or **Vagrant** user credentials. 90 | ```bash 91 | ssh @ -p 2222 92 | ``` 93 | 94 | ## 🔑 User Login 95 | Default users based on the Vagrant image are: 96 | 97 | 1. Administrator 98 | - Username: Administrator 99 | - Password: vagrant 100 | 1. User 101 | - Username: vagrant 102 | - Password: vagrant 103 | 104 | ## 📚 Further Reading and Resources 105 | 106 | - [Windows Vagrant Tutorial](https://github.com/SecurityWeekly/vulhub-lab) 107 | - [Vagrant image: peru/windows-server-2022-standard-x64-eval](https://app.vagrantup.com/peru/boxes/windows-server-2022-standard-x64-eval) 108 | - [Vagrant by HashiCorp](https://www.vagrantup.com/) 109 | - [Windows Virtual Machine in a Linux Docker Container](https://medium.com/axon-technologies/installing-a-windows-virtual-machine-in-a-linux-docker-container-c78e4c3f9ba1) 110 | - [GPU inside a container](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html) --------------------------------------------------------------------------------