Building a Windows driver using Docker
Previously I talked about how useful Docker was for build environments. Now I'm going to give a practical example of a simple Docker image that is able to build a driver using the WinDDK 7.1
This is going to use a Linux x64 based Docker image so that it will work almost anywhere (MacOs, Linux Desktop, and Windows all can run Linux x64 Docker images). The building will be done using WinDDK 7.1. We will use Wine inside the Docker container to run the Windows WinDDK executables. The end result will be to be able to build the HelloWorld driver example.
One of the huge benefits with Docker is that images can easily be shared. Unfortunately due to the WinDDK being owned by Microsoft, the license agreement for the WinDDK prevents people from publicly sharing it or distributing it in any manner. Therefore I can not provide a complete Docker image that contains the WinDDK. Instead I will provide the instructions for building it yourself.
The first step is getting the WinDDK as a .tar.gz file. This is not the format the Microsoft deliver it in though. For this step you will need a Windows OS. If you don't have a Windows OS then you can install VirtualBox for free and download and install Windows 10 from Microsoft. You do not need a key to install Windows initially and once the next step is done the VM can be discarded.
Install the WinDDK to the default location. You only need to install the Build Environments.
This does not take very long to install. Once done there will be the directory C:\WinDDK created.
Now run the following command to create the tar.gz
tar czf WINDDK7.1.tar.gz C:\WinDDK
This will take a while and produce a tar file around 550 MB. Keep a copy of the tar file and you can now discard the VM if you choose to.
The following is a simple Dockerfile along with some additional files for creating an image containing the WinDDK and Wine.
(Files available in this zip)
FROM ubuntu:20.04 # Set useful variables ENV DEBIAN_FRONTEND=noninteractive ENV \ WINEDEBUG=-all \ WINEDLLOVERRIDES="vcruntime140_1=n" RUN set -ex ;\ dpkg --add-architecture i386 ;\ apt-get update ;\ apt-get install -y wine-development ;\ rm -rf /var/lib/apt/lists/* ;\ wine wineboot --init; while pgrep wineserver; do sleep 1; done ;\ mv /root/.wine/drive_c /drive_c ;\ rm /root/.wine/dosdevices/c: ;\ ln -s /drive_c /root/.wine/dosdevices/c: ;\ chmod o+rwx /root /root/.wine ;\ chmod o+rw /root/.wine/*.reg ;\ chmod -R a+w /drive_c ;\ true ADD ["WINDDK7.1.tar.gz", "/drive_c/"] ADD ["doskey.bat", "/drive_c/windows/"] ADD ["setenvbuild.sh", "/usr/local/bin/"] ADD ["setenvbuild.bat", "/drive_c/windows/"] RUN chmod +x /usr/local/bin/setenvbuild.sh ENTRYPOINT ["setenvbuild.sh"]
@echo off rem Dummy file to suppress error message that doskey is missing (its not in wine)
#!/usr/bin/bash wine cmd /c setenvbuild.bat "$@"
@echo off pushd call C:\WinDDK\7600.16385.1\bin\setenv C:\WinDDK\7600.16385.1 %* popd build -cZw
Build the Docker image
Put the above files into a directory along with WINDDK7.1.tar.gz. (A zip of the above files can be downloaded here)
Run the following command:
docker build -t build-winddk7.1 .
This will create a docker image named "build-winddk7.1". This image can now be used to build the HelloWorld driver sample. In a directory containing the source and makefiles
for the HelloWorld driver run the following command (on a Windows host)
docker run --rm -v %CD%:/build -w /build build-winddk7.1
Or on a non Windows host use:
docker run --rm -v $PWD -w $PWD:$PWD build-winddk7.1
This will build the driver. Additionally you can add parameters at the end of the command line that will be passed to the WinDDK setenv.bat program. For example to build x64 use:
docker run --rm -v $PWD -w $PWD:$PWD build-winddk7.1 x64
This is a very basic Docker image. Many improvements can be made to make it more useful, for example adding in CMake rather than using the WinDDKs makefile system. This should serve as a good base for demonstrating how useful Docker can be for build environments. Once the Docker image is made and shared there is no need for anyone else in the team to have to worry about setting up the build environment on their own computer, they just use the Docker image and everything is self contained.