Windows docker images
Windows images are used for some features available only in windows. The main reason is usually building an IL2CPP version of the application.
To build applications effectively in terms of build time, the very base image is a .NET framework 4.8. It's cached on GitHub actions runners and we truly need .NET. The base Windows image can be found in https://github.com/game-ci/docker.
Features
- Git
- Choco package manager
Limitations
Microsoft does not allow redistribution of Visual Studio build tools
Microsoft does not permit publishing images with VS Build tools which are needed for IL2CPP builds
discussion
.
You will encounter exceptions in the Unity log similar to
error: Could not set up a toolchain for Architecture x64. Make sure you have the right build tools installed for il2cpp builds.
Expand this section for a full log example.
error: Could not set up a toolchain for Architecture x64. Make sure you have the right build tools
installed for il2cpp builds. Details: IL2CPP C++ code builder is unable to build C++ code. In order
to build C++ code for Windows Desktop, you must have one of these installed: * Visual Studio 2022 or
newer with C++ compilers and Windows 10 SDK (recommended) * Visual Studio 2019 with C++ compilers and
Windows 10 SDK * Visual Studio 2017 with C++ compilers and Windows 10 SDK * Visual Studio 2015 with
C++ compilers and Windows 10 SDK Visual Studio 2017 (or newer) is detected using `vswhere.exe` as well
as VSCOMNTOOLS environment variables. Visual Studio 2015 is detected by looking at "SOFTWARE\Microsoft\VisualStudio\14.0_Config\InstallDir"
in the registry as well as VSCOMNTOOLS environment variables. Windows 10 SDK is detected by looking
at "SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v10.0\InstallationFolder" in the registry.
Unable to detect any compatible Visual Studio installation! * Found Visual Studio 2022 installation
without C++ tool components Windows 10 SDK is not installed. You can install from here: https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk/
There are two options to avoid this obstacle:
- (Recommended) Inject/mount Microsoft Visual Studio with VC++ and Windows 10 SDK from the host system into the container during runtime.
- Build a custom image and push it to a docker registry.
Option 1. Injecting VC++ from the host system into the container
These instructions have been validated with Visual Studio 2022 and Unity 2021 LTS.
Install Visual Studio Build Tools
The recommended way to install the correct dependencies on the host is with Chocolatey. This works with Windows 10/11, Windows Server, and Windows Server Core.
choco install visualstudio2022-workload-vctools --no-progress -y
There is a way to install the same dependencies from the graphical Visual Studio Installer, but the workload component options in the installer frequently change.
The following directories need to be bind-mounted into the container
- C:\Program Files (x86)\Windows Kits
- C:\Program Files (x86)\Microsoft Visual Studio
- C:\Program Files\Microsoft Visual Studio
- C:\ProgramData\Microsoft\VisualStudio
Please confirm all of the above directories exist in your installation. Some may be missing and things might still work OK without them. Omit the missing directories in the following steps.
Docker run example
docker run `
-v "C:\Program Files (x86)\Windows Kits:C:\Program Files (x86)\Windows Kits" `
-v "C:\Program Files (x86)\Microsoft Visual Studio:C:\Program Files (x86)\Microsoft Visual Studio" `
-v "C:\Program Files\Microsoft Visual Studio:C:\Program Files\Microsoft Visual Studio"
-v "C:\ProgramData\Microsoft\VisualStudio:C:\ProgramData\Microsoft\VisualStudio" `
unityci/editor:windows-$env:UNITY_VERSION-windows-il2cpp-$env:UNITY_IMAGE_VERSION
Gitlab runner config.toml example
#...
volumes = [
"C:\\Program Files (x86)\\Windows Kits:C:\\Program Files (x86)\\Windows Kits",
"C:\\Program Files\\Microsoft Visual Studio:C:\\Program Files\\Microsoft Visual Studio",
"C:\\Program Files (x86)\\Microsoft Visual Studio:C:\\Program Files (x86)\\Microsoft Visual Studio",
"C:\\ProgramData\\Microsoft\\VisualStudio:C:\\ProgramData\\Microsoft\\VisualStudio"
]
#...
Option 2. Building a custom image
ARG UNITY_VERSION=''
ARG UNITY_IMAGE_VERSION='3'
FROM unityci/editor:windows-${UNITY_VERSION}-windows-il2cpp-${UNITY_IMAGE_VERSION}
RUN choco install visualstudio2022-workload-vctools --no-progress -y
Licenses are not valid between containers runs
This behaviour is different to Ubuntu containers where it's possible to use a single license for even a few different runners.
In Windows, it's necessary to acquire a license every time and return it after a building process. License files for every run are identical apart from the last four symbols of the machine hash code. This restriction has not been solved yet
Scripting example
The simplest way is to write a couple of scripts (copied from
Unity3d docs
) and wrap it to the
try-finally block
Note: Path to Unity3d is
C:\Program Files\Unity\Hub\Editor\{UNITY_EDITOR_VERSION}\Editor\Unity.exe
try {
build.ps1
} finally {
return-license.ps1
}
GitLab example
unity-windows-il2cpp-build:
variables:
UPM_CACHE_ROOT: $CI_PROJECT_DIR/.upm
UNITY_IMAGE_VERSION: "3"
UNITY_MODULE: "il2cpp"
UNITY_IMAGE_PREFIX: "unityci/editor"
# Do not use quotes around this argument
UNITY_EXECUTABLE: C:\Program Files\Unity\Hub\Editor\$UNITY_VERSION\Editor\Unity.exe
BUILD_COMMAND: "BuildCommand.PerformBuild"
BUILD_TARGET: "Win64"
BUILD_NAME: "example"
BUILD_PATH: "dist/"
image: $UNITY_IMAGE_PREFIX:windows-$UNITY_VERSION-$UNITY_MODULE-$UNITY_IMAGE_VERSION
tags:
- Docker-Windows
cache:
- key: "$UNITY_VERSION-$BUILD_TARGET-Library"
paths:
- $CI_PROJECT_DIR/Library/
- key: "unity3d"
paths:
- $UPM_CACHE_ROOT
artifacts:
expire_in: "1 day"
paths:
- dist
needs:
- get-unity-version
script:
- |
try {
& $env:UNITY_EXECUTABLE `
-projectPath $env:CI_PROJECT_DIR `
-quit `
-batchmode `
-nographics `
-buildTarget $env:BUILD_TARGET `
-executeMethod $env:BUILD_COMMAND `
-logFile - `
-username $env:UNITY_USERNAME `
-password $env:UNITY_PASSWORD `
-serial $env:UNITY_SERIAL `
| Out-Host
}
finally {
& $env:UNITY_EXECUTABLE `
-quit `
-batchmode `
-nographics `
-logFile - `
-username $env:UNITY_USERNAME `
-password $env:UNITY_PASSWORD `
-returnlicense `
| Out-Host
}
Troubleshooting: GitLab
Gitlab doesn't have (or has few) shared docker-windows runners
There is no other option right now, but
use a private runner. Please, set the docker-windows
type of the runner
Default docker-for-windows settings are very resource-mean. It uses a single core and 1Gb of RAM. That's why the custom configuration is highly recommended
config.toml
#...
[runners.docker]
cpus = "12"
memory = "13g"
hostname = "dockerImage"
#...
Note: hostname
doesn't influence the performance, but one day can help with license
association to a machine
Default shell for GitLab Runner is PowerShell Core
GitLab Runner changed the default docker-windows executor shell in v14 to PowerShell Core which is a newer version of PowerShell than is distributed with base windows container images.
There are two workarounds:
- (Recommended) Manually specify the shell in the config to be the pre-v14 default.
- Build a custom image including PowerShell Core and push it to a docker registry.
Option 1: Change it in the config.toml
[[runners]]
shell = "powershell"
Option 2: Install PowerShell Core
ARG UNITY_VERSION=''
ARG UNITY_IMAGE_VERSION='3'
FROM unityci/editor:windows-${UNITY_VERSION}-windows-il2cpp-${UNITY_IMAGE_VERSION}
RUN choco install pwsh --no-progress -y
Then push it to a docker registry. Installing pwsh
during a pipeline doesn't help.
Git-ssh dependency package checkout fails
The base image windowsservercore
is too old and has some outdated packages. One of them, OpenSSH
has a bug that breaks the remote
repository signature check.
The best option here is to replace it with something more recent
# Manually remove an old ssh-agent service
sc.exe delete ssh-agent
choco install openssh -params '"/SSHAgentFeature"' --no-progress -y
$env:GIT_SSH="C:\Program Files\OpenSSH-Win64\ssh.exe"
Note: ssh-add
must be used from a different location,
C:\Program Files\OpenSSH-Win64\ssh-add.exe