Windows 的 Docker 镜像使用体验

微软在 Docker Hub 上提供了 Windows 的一些镜像,其中感觉比较使用的是这两个

- `nanoserver`
- `servercore`

其中那个 `nanoserver` 只有200多MB,很难想象 Windows 核心中的核心只有这么大。但是,这个镜像里面几乎什么都没有,连 Powershell 都没有!这同样让人难以置信。捣鼓了半天,我也不知道这个镜像能用来做什么。可能就是单纯提供一个运行环境,运行一些依赖库齐全的服务?

不管怎么说,我的目的是构建一个环境可以用来编译我们的 [libgwmodel](https://github.com/GWmodel-Lab/libgwmodel) 库,研究了一下,应该只能使用 `servercore` 了。这个镜像虽然比较大,但是也只有 1.3G,和 Windows 本体比起来,还是要小了不少的。这个镜像有 Powershell,所以基本上可以使用 `powershell.exe` 代替 `cmd.exe` 运行命令。

虽然 Powershell 有一个包管理器和模块管理器,微软也出了一个 WinGet 用于安装一些软件。但是我尝试了一下发现,WinGet 安装后还是无法使用,可能是要设置环境变量什么的。这里还有一个坑:直接从 GitHub 上下载的 WinGet 的 AppxBundle 包是无法直接安装的,最好是用 `Install-Package` 命令安装。而且 WinGet 安装 MSVC 编译器不是非常方便。

那么干脆使用 Chocolatey 作为包管理器好了。官方文档也提供了安装脚本

```powershell
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iwr https://community.chocolatey.org/install.ps1 -UseBasicParsing | iex
```

直接运行就没有什么问题了。安装完成后,使用 `choco` 命令即可安装其他包。我们这个情况下,需要用的基础工具主要是 MSVC Git CMake 这些,所以用下面这个命令安装

```powershell
choco install visualstudio2019-workload-vctools git cmake
```

这要这几个工具安装好了,基本已经成功一半了。注意安装完成之后要把 Git 和 CMake 安装目录下面的 `bin` 目录加到 `Path` 环境变量里面去

```powershell
$env:Path='C:\Program Files\Git\bin;C:\Program Files\CMake\bin;'+$env:Path
```

还有一些依赖库需要安装,我们使用 Vcpkg 就可以。直接在 `C:\` 下面安装即可。

```powershell
git clone https://github.com/microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.bat
$env:VCPKG_DEFAULT_TRIPLET='x64-windows'
./vcpkg install armadillo openblas gsl catch2
```

然后克隆代码仓库,应该问题就不大了。

```powershell
git clone https://github.com/GWmodel-Lab/libgwmodel.git
cd libgwmodel
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE='C:\vcpkg\scripts\buildsystems\vcpkg.cmake'
cmake --build build
```

但是 GitHub Actions 好像还不支持构建 Windows 镜像?反正我是遇到了一些问题,好像是高权限模式无法使用。所以只能本地构建然后推送了。

```Dockerfile
FROM mcr.microsoft.com/windows/servercore:ltsc2022

SHELL ["powershell", "-command"]
RUN Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iwr https://community.chocolatey.org/install.ps1 -UseBasicParsing | iex
RUN choco install visualstudio2019-workload-vctools git cmake -q -y
RUN $newPath=(('C:\Program Files\Git\bin', 'C:\Program Files\CMake\bin') + ([Environment]::GetEnvironmentVariable('Path', 'Machine') -split ';')) -join ';'; [Environment]::SetEnvironmentVariable('Path', $newPath, 'Machine'); [Environment]::SetEnvironmentVariable('VCPKG_DEFAULT_TRIPLET', 'x64-windows', 'Machine')
RUN git clone https://github.com/microsoft/vcpkg; .\vcpkg\bootstrap-vcpkg.bat; .\vcpkg\vcpkg install armadillo gsl openblas[threads] catch2
RUN rm -Recurse C:\vcpkg\buildtrees; rm -Recurse C:\vcpkg\downloads; rm -Recurse C:\vcpkg\packages

ENTRYPOINT powershell.exe
```