POC – Providing Windows Environments on Linux Hosts via Docker

My proof of concept!

For student projects, it is often necessary to provide isolated working environments where students can experiment, develop, and test their skills safely. My proposed solution is to use Docker to deploy Windows machines accessible via RDP (Remote Desktop Protocol), thus offering a temporary and flexible « sandbox. » This project explores implementing this idea using Dockurr (https://github.com/dockurr/windows), a free and open-source project that allows running Windows environments in Docker containers on Linux hosts.

Project Objective

The goal of this project is to create an automated script capable of generating, configuring, and deploying multiple Windows containers accessible via RDP. Each student will have their own isolated virtual machine with administrator rights to perform advanced tasks. These environments will be created automatically and will have a limited lifespan, ideal for a few hours of work sessions.

Introducing Dockurr

Dockurr is a free and open-source project that allows running Windows desktop and Windows Server installations in Docker containers. It can be done on a Docker Linux host using KVM acceleration without installing Docker Desktop or encountering typical compatibility issues with mixing operating systems. Dockurr uses KVM (https://www.redhat.com/en/topics/virtualization/what-is-KVM) and QEmu (https://www.qemu.org).

The Automation Script

The Bash script below automates the creation of Windows containers, their configuration, and the deployment of these containers with RDP access. Here is the script in detail:

#!/bin/bash

# Number of containers to create
NUM_CONTAINERS=10

# Base port for services
# For streaming via web browser
BASE_PORT=8000
# For RDP
RDP_BASE_PORT=3389

# Base path for volumes
BASE_STORAGE_PATH="/home/vdi/windows"

# Source directory for files to copy
SOURCE_PATH="/home/vdi/basehdd"

# Output file
OUTPUT_FILE="containers_info.txt"
echo "ServicePort;RDPPort;Username;Password" > $OUTPUT_FILE

# Function to generate a random 8-character password
generate_password() {
  tr -dc 'A-Za-z0-9' < /dev/urandom | head -c 8
}

# Create a Docker bridge network (if necessary)
docker network inspect windows_network >/dev/null 2>&1 || docker network create windows_network

# Loop to create each container
for i in $(seq 1 $NUM_CONTAINERS); do
  # Generate dynamic ports
  PORT=$((BASE_PORT + i))
  RDP_PORT=$((RDP_BASE_PORT + i))
  
  # Container name
  CONTAINER_NAME="windows_${i}"
  
  # Dynamic storage path
  STORAGE_PATH="${BASE_STORAGE_PATH}_${i}"
  
  # Create the storage directory if it does not exist
  mkdir -p $STORAGE_PATH || { echo "Failed to create directory $STORAGE_PATH"; exit 1; }
  
  # Generate the password
  PASSWORD=$(generate_password)
  
  # Generate the dynamic docker-compose.yml file
  cat > $STORAGE_PATH/docker-compose.yml <<EOF
version: "3"
services:
  $CONTAINER_NAME:
    image: dockurr/windows
    container_name: $CONTAINER_NAME
    environment:
      RAM_SIZE: "4G"
      CPU_CORES: "4"
      VERSION: "ltsc10"
      USERNAME: "admin"
      PASSWORD: "$PASSWORD"
      DISK_SIZE: "64G"
      LANGUAGE: "French"
      REGION: "fr-FR"
      KEYBOARD: "fr-FR"
    devices:
      - /dev/kvm
    volumes:
      - $STORAGE_PATH:/storage
    cap_add:
      - NET_ADMIN
    ports:
      - "${PORT}:8006"
      - "${RDP_PORT}:3389/tcp"
      - "${RDP_PORT}:3389/udp"
    stop_grace_period: 2m
    restart: on-failure
    networks:
      - windows_network

networks:
  windows_network:
    external: true
EOF

  # Copy files from the source directory to the container's storage directory
  cp -r -f $SOURCE_PATH/* $STORAGE_PATH/ || { echo "Failed to copy files to $STORAGE_PATH"; exit 1; }
  
  # Start the container with docker-compose from the container directory
  (cd $STORAGE_PATH && docker-compose up -d) || { echo "Failed to start container $CONTAINER_NAME"; exit 1; }
  
  # Write the container information to the output file
  echo "$PORT;$RDP_PORT;utilisateur;$PASSWORD" >> $OUTPUT_FILE
done

echo "All containers have been created, files copied, and started successfully."

Script Explanation

Initializing Parameters:

  • The script defines the number of containers, base ports, and storage paths.

Creating the Docker Network:

  • The script checks if the Docker windows_network exists and creates it if necessary.

Creating Containers in a Loop:

  • For each container, the script generates dynamic ports, creates a storage directory, and generates a random password.
  • A docker-compose.yml file is created in each storage directory.
  • Necessary files are copied from the source directory to the container’s storage directory.
  • The container is started using Docker Compose.
  • Connection information is recorded in an output file.

Advantages of this Approach

Isolation and Security:

  • Each student has access to their own isolated virtual machine, reducing the risk of interference between projects.

Easy Administration:

  • Students have administrative rights on their machines, allowing them to install software and configure the environment as needed.

Automation and Efficiency:

  • The script automates the creation, configuration, and deployment of containers, significantly reducing the time and effort required.

Flexibility and Scalability:

  • This system can be easily adjusted to create more or fewer containers as needed.

Future Prospects

To further optimize this project, consider:

Using Differential Disks:

  • Instead of copying the base image file, all containers can use this base image and create differential files for modifications. This approach saves disk space and improves performance. This feature is essential for the project’s viability!

Automatic Container Lifespan Management:

  • Implement a mechanism to automatically delete containers after a period of inactivity or at the end of a work session.

Web Interface for Container Management:

  • Develop a web interface for administrators to monitor and manage containers more intuitively.

Conclusion

This project demonstrates how Dockurr and Docker can be used to provide temporary and isolated development environments for students. With this automation script, administrators can quickly deploy Windows virtual machines accessible via RDP, offering an efficient and flexible solution for educational projects. This system ensures that each student has a clean and secure environment while facilitating resource and configuration management. The proposed future prospects can further enhance the efficiency and flexibility of this project, meeting the diverse needs of educational institutions.