将 F# 4.5 安装到 Docker 容器

Install F# 4.5 to Docker Container

我需要在 .NET Framework(而非 .NET Core)上使用 F# 4.5 运行ning。我希望这个环境 运行 在 docker 容器中,因为它会定期 运行 在我们的 Jenkins 构建服务器上。我以为我可以使用现有的 .NET Framework SDK Image 但它只有 F# for .NET Core/.NET 5.

所以我尝试将 F# 安装到 运行ning 容器中(如果可行,我会把它添加到图像本身)但我没有任何运气。这是我的尝试...

  1. 创建 project 文件夹

  2. Download vs_BuildTools.exeproject

  3. 使用 .NET Framework SDK 4.8 映像创建 Dockerfile

    FROM mcr.microsoft.com/dotnet/framework/sdk:4.8-windowsservercore-ltsc2019 as build
    SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
    RUN Set-ExecutionPolicy Bypass; \
        iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')); \
        choco install sonarscanner-msbuild-net46 -y; \
        choco install jdk8 -y; \
        choco install powershell-core -y;
    
    # Install Crystal Reports for Visual Studio
    WORKDIR /installers
    # hack in oledlg dll so that Crystal Runtime will install. See
    #  for more info
    COPY Resources/Files/64/oledlg.dll /windows/syswow64/oledlg.dll
    COPY Resources/Files/32/oledlg.dll /windows/system32/oledlg.dll
    ARG CR_DOWNLOAD_URL=https://origin.softwaredownloads.sap.com/public/file/0020000001263562020
    ARG CR_HASH=8665A5192240163177B0FDC7EA87C94A17F0476EFFF593FD90CB65361FC00A63
    SHELL ["pwsh", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
    RUN Invoke-WebRequest "$env:CR_DOWNLOAD_URL" -OutFile 'cr.msi'; \
        if ((Get-FileHash 'cr.msi').Hash -ne "$env:CR_HASH") { \
            Write-Error 'Crystal Reports hashes do not match. Stopping build.' \
        } \
        Start-Process 'msiexec.exe' -Wait -ArgumentList '/i "C:\installers\cr.msi" /quiet /qn /norestart /L*V "C:\Windows\Temp\cr_install.log"'; \
        Remove-Item 'cr.msi'
    
    FROM build as dev
    WORKDIR /dev
    
  4. 建立我的形象

    docker build -t my-project . --target dev
    
  5. 运行我的容器

    docker run -it --rm -v "${pwd}:C:\dev" --name my-project my-project
    

    将卷装载到当前本地目录使我可以访问之前下载的 vs_BuildTools.exe。

  6. 安装可选的 F# 组件。我尝试了几种不同的选择

    1. 安装带有可选组件的 ManagedDesktopBuildTools

      start /w vs_BuildTools --add Microsoft.VisualStudio.Workload.ManagedDesktopBuildTools --quiet --norestart --nocache --wait --includeOptional
      
      start /w vs_BuildTools modify --add Microsoft.VisualStudio.Workload.ManagedDesktopBuildTools --quiet --norestart --nocache --wait --includeOptional
      
    2. 显式安装 F# 组件

      start /w vs_BuildTools --add Microsoft.VisualStudio.Component.FSharp.MSBuild --quiet --norestart --nocache --wait
      
      start /w vs_BuildTools modify --add Microsoft.VisualStudio.Component.FSharp.MSBuild --quiet --norestart --nocache --wait
      

在所有情况下,我都会得到各种各样的信息,包括...

[08f8:0001][2021-05-10T20:49:21] Visual Studio Installer Version: 2.9.3365
[08f8:0001][2021-05-10T20:49:21] Raw Command line: "C:\Program Files (x86)\Microsoft Visual Studio\Installer\setup.exe"  modify --add Microsoft.VisualStudio.Workload.ManagedDesktopBuildTools --quiet --norestart --nocache --includeOptional --locale en-US --activityId "d43641b0-241b-48be-b6ff-6625487b134e"
[08f8:0001][2021-05-10T20:49:21] Warning: Closing the installer with exit code 87
... more logs ...
[08f8:0001][2021-05-10T20:49:22] Warning: Failed to parse the command line arguments: The current operation needs either --channelId and
--productId or --installPath Usage: setup.exe modify [options]
... more logs ...
[08f8:0001][2021-05-10T20:49:22] Warning: Shutting down the application with exit code 87
[08f8:0001][2021-05-10T20:49:22] Closing the installer with exit code 87
[08f8:0001][2021-05-10T20:49:22] Exit Code: 87

[07b8:0012][2021-05-10T22:33:50] Warning: Shutting down the application with exit code 1
[07b8:0012][2021-05-10T22:33:50] Warning: Visual Studio Build Tools 2019 (2) is already installed.
[07b8:0001][2021-05-10T22:33:50] Releasing singleton lock.
[07b8:0001][2021-05-10T22:33:50] Releasing singleton lock succeed.
[07b8:0001][2021-05-10T22:33:50] Releasing singleton lock.
[07b8:0001][2021-05-10T22:33:50] Singleton lock does not exist. Releasing singleton lock skipped.
[07b8:0001][2021-05-10T22:33:50] Closing the installer with exit code 1

甚至

[044c:0001][2021-05-10T22:55:26] Exception occured while trying to write telemetry session to the network. One or more errors occurred.
  at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at Microsoft.VisualStudio.Setup.Services.Telemetry.FlushTelemetrySession(Boolean shouldRecreate)

我做错了什么?

TLDR

我能够通过安装 F# Compiler Tools using paket 解决问题。 .NET Framework(或单声道)上的 F# 4.5 运行s 的 F# 编译器工具不同于 .NET Core(或 .NET 5)上的 F#5 运行s。

详情

创建 Dockerfile

我的 Dockerfile 看起来与以前没有太大区别。我仍然基于 Microsoft .NET Framework SDK 4.8 图像,因为我想访问 .NET SDK。

FROM mcr.microsoft.com/dotnet/framework/sdk:4.8-windowsservercore-ltsc2019 as build
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

#
# INSTALL SAP CRYSTAL REPORTS DEVELOPER VERSION FOR MICROSOFT VISUAL STUDIO STUDIO 32 BIT & 64 BIT
# Downloads for CR can be found at https://origin.softwaredownloads.sap.com/public/site/index.html
#
WORKDIR /installers

# Add oledlg dlls so that the Crystal Reports runtime will install. For more infomation see:
# 
COPY Resources/Files/64/oledlg.dll /windows/syswow64/oledlg.dll
COPY Resources/Files/32/oledlg.dll /windows/system32/oledlg.dll

ARG CR_DOWNLOAD_URL_32=https://origin.softwaredownloads.sap.com/public/file/0020000000195592021
ARG CR_32_HASH=425D88E82832784A9E53897C43F54A6E0423FFCBFA536C12253378E5C4646CD7
ARG CR_DOWNLOAD_URL_64=https://origin.softwaredownloads.sap.com/public/file/0020000000195602021
ARG CR_64_HASH=2BAB57DC3E8C69A2DB3835FEFF11E52B5D9C19020DC9A08302A97618F8304C1B

RUN Invoke-WebRequest "$env:CR_DOWNLOAD_URL_32" -OutFile 'cr32.msi'; \
    Invoke-WebRequest "$env:CR_DOWNLOAD_URL_64" -OutFile 'cr64.msi'; \
    if ((Get-FileHash 'cr32.msi').Hash -ne "$env:CR_32_HASH") { \
        Write-Error 'Crystal Reports 32 bit hashes do not match. Stopping build.' \
    } \
    if ((Get-FileHash 'cr64.msi').Hash -ne "$env:CR_64_HASH") { \
        Write-Error 'Crystal Reports 64 bit hashes do not match. Stopping build.' \
    } \
    Start-Process 'msiexec.exe' -Wait -ArgumentList '/i "C:\installers\cr32.msi" /quiet /qn /norestart /L*V "C:\Windows\Temp\cr32_install.log"'; \
    Start-Process 'msiexec.exe' -Wait -ArgumentList '/i "C:\installers\cr64.msi" /quiet /qn /norestart /L*V "C:\Windows\Temp\cr64_install.log"'; \
    Remove-Item 'cr32.msi'; \
    Remove-Item 'cr64.msi';

FROM build as dev
WORKDIR /dev

构建图像

当 Dockerfile 解决后,我们构建图像。

docker build -t fsharp-image . --target dev

运行容器

docker run -it --rm -v "$(pwd):C:\dev" --name fsharp-image fsharp-image

安装包

我使用首选 (.NET Core) 选项遵循 Get Started Paket 说明。命令在 运行ning 容器中执行。

  1. 安装和恢复数据包
    dotnet new tool-manifest
    dotnet tool install paket
    dotnet tool restore
    
  2. 创建数据包依赖文件
    dotnet paket init
    

安装 F# 编译器工具

现在安装了 Paket,我们可以安装 F# 编译器工具。

paket add FSharp.Compiler.Tools --version 10.2.3

确认 F# 4.5 安装

为了确认 F# 4.5 安装,我们 运行 以下内容。

packages\FSharp.Compiler.Tools\tools\fsi.exe

这应该是输出

Microsoft (R) F# Interactive version 10.2.3 for F# 4.5
Copyright (c) Microsoft Corporation. All Rights Reserved.

For help type #help;;

运行 TestOpenCrystalReportsDocument.fsx

然后我创建了一个小脚本来测试完整的安装。

// TestOpenCrystalReportsDocument.fsx
#r "CrystalDecisions.CrystalReports.Engine"
#r "CrystalDecisions.Shared"

open CrystalDecisions.CrystalReports.Engine
open CrystalDecisions.Shared

let openDoc path =
    let doc = new ReportDocument()
    doc.Load path
    doc

printfn "OPEN DOC"
let doc = openDoc "C:\dev\test.rpt"
printfn "SUCCESS"

最后我们运行脚本

packages\FSharp.Compiler.Tools\tools\fsi.exe TestOpenCrystalReportsDocument.fsx

输出显示我们没有错误!

OPEN DOC
SUCCESS

总结

最后,我提交了以下文件。

  • Docker 文件
  • paket.dependencies
  • paket.lock
  • .config/dotnet-tools.json

每当我重新 运行 容器时,我只需要执行 dotnet tool restoredotnet paket restore 来重新安装 paket 和 F# 4.5 编译器工具。