How to create an Azure DevOps Self-Hosted Build Agent Docker Image based on Windows
Updated on 2021-08-28 09:54
Azure DevOps provides basically two types of agents: Microsoft-Hosted agents and Self-Hosted agents.
Microsoft-Hosted agents are completely managed by Microsoft in the cloud, can be based on Windows, Ubuntu or macOS. For each OS, a set of software in included in the VM image used to spin up a new VM when a new job need to be executed (more details here).
The main advantage in using Microsoft-Hosted agents is that most of the time provide everything you need to build and deploy your solution without the need to set up, configure and maintain the OS and software packages required.
The drawbacks are that you don’t have control on the CPU and memory provided with the VM and you cannot have access to internal networks (everything the agent access need to be exposed on Internet).
More details on capabilities and limitations of Microsoft-Hosted agents are here.
Self-Hosted agents are basically agents that runs wherever you need. You have to take care about everything: the installation, set up and updates of the OS, all software packages required by your pipelines to build and deploy your solutions, the network configurations to reach the code repository, the Azure resources and, if required, the VMs where you will deploy software components. The supported operative systems are Windows, Ubuntu and macOS.
In the last project I have worked on, we had the need to deploy many Self-Hosted agents and, because the solution was based on .NET Framework 4.8, we had to use Windows based agents.
So, considering that we had to prepare 4 different environments (Development, Quality, Performance and Production), and we decided to install two agents for each environment, we started analyzing the possibility to prepare a Windows based Docker image for this purpose.
Prepare your Dockerfile
The first step to take is to prepare the Dockerfile needed to create the image.
# escape=`# Use the latest Windows Server Core image with .NET Framework 4.8.FROM mcr.microsoft.com/dotnet/framework/sdk:4.8-windowsservercore-ltsc2019# Restore the default Windows shell for correct batch processing.SHELL["cmd","/S","/C"]# Download the Build Tools bootstrapper.ADD https://aka.ms/vs/16/release/vs_buildtools.exe C:\TEMP\vs_buildtools.exe# Install Build Tools with the workloads you need, excluding workloads and components with known issues.# More details here: https://docs.microsoft.com/en-us/visualstudio/install/workload-component-id-vs-build-toolsRUN C:\TEMP\vs_buildtools.exe --quiet --wait --norestart --nocache --includeRecommended ` --installPath C:\BuildTools ` --add Microsoft.VisualStudio.Workload.AzureBuildTools ` --add Microsoft.VisualStudio.Workload.OfficeBuildTools ` --add Microsoft.VisualStudio.Workload.MSBuildTools ` --add Microsoft.VisualStudio.Workload.NetCoreBuildTools ` --add Microsoft.Net.Core.Component.SDK.2.1 ` --remove Microsoft.VisualStudio.Component.Windows10SDK.10240 ` --remove Microsoft.VisualStudio.Component.Windows10SDK.10586 ` --remove Microsoft.VisualStudio.Component.Windows10SDK.14393 ` --remove Microsoft.VisualStudio.Component.Windows81SDK `|| IF "%ERRORLEVEL%"=="3010" EXIT 0WORKDIR /azpCOPY start.ps1 .# Define the entry point for the docker container.# This entry point starts the developer command prompt and launches the PowerShell shell.ENTRYPOINT["C:\\BuildTools\\Common7\\Tools\\VsDevCmd.bat","&&","powershell.exe",".\\start.ps1"]
As you can see, we use as base image a Windows Server Core image with .NET Framework 4.8 already installed. Then we download the Visual Studio Build Tools and run the installation in quiet mode (an unattended mode that doesn’t require user interaction).
Is very important to analyze the Visual Studio Build Tools setup arguments. As you can see we use the –add parameter to define all the workloads we need to install. A workload is a set of features and applications installed, and you can find the list of workloads and the features included in each workload here.
Obviously you can adapt this part with the workloads you need. In our case we had to add a lot of workloads because of the dependencies required by our solution to build correctly.
After the installation, the Dockerfile copies a PowerShell script called start.ps1 in the azp folder and executes it. The script is the following: