我有一个构建为x86的.NET Core 3.1.3 Web API项目。它必须是x86,因为它通过dllimport来使用x86 C++ DLL。在Docker之外,应用程序按预期运行。但是,一旦添加Windows Docker支持,它就会立即失败。我从SO研究中相信它失败了,因为Microsoft没有为.NET Core提供任何x86基本镜像。默认的Windows Docker基本镜像当前为mcr.microsoft.com/dotnet/core/aspnet:3.1-nanoserver-1903。
我尝试使用mcr.microsoft.com/windows/servercore:1909作为基本镜像,但是随后出现错误消息“无法启动程序:'C:\ Program Files \ dotnet \ dotnet.exe”。假定这是因为此exe在使用的基本镜像上不存在。并且,大概对于x86,实际上将需要“C:\ Program Files(x86)\ dotnet \ dotnet.exe”。
我当前的Dockerfile是:
FROM mcr.microsoft.com/windows/servercore:1909 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/windows/servercore:1909 AS build
WORKDIR /src
COPY ["WAPTCoreWebService/WAPTCoreWebService.csproj", "WAPTCoreWebService/"]
RUN dotnet restore "WAPTCoreWebService/WAPTCoreWebService.csproj"
COPY . .
WORKDIR "/src/WAPTCoreWebService"
RUN dotnet build "WAPTCoreWebService.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "WAPTCoreWebService.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "WAPTCoreWebService.dll"]
我是否正确解释了此错误。如果没有,那是什么意思?如果是这样,我如何添加支持以在此镜像中构建.NET Core应用程序的x86版本?我是否需要以某种方式下载并运行dotnet-runtime-3.1.3-win-x86.exe?如果是这样,怎么办?
更新 2020年4月29日
基于Matt Thalman的回答,我构建了一个自定义镜像,以包含x86版本的.NET Core SDK。 Docker文件为:
# escape=`
# Installer image
FROM mcr.microsoft.com/windows/servercore:1909 AS installer
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
# Retrieve .NET Core SDK
RUN $dotnet_sdk_version = '3.1.201'; `
Invoke-WebRequest -OutFile dotnet.zip https://dotnetcli.azureedge.net/dotnet/Sdk/$dotnet_sdk_version/dotnet-sdk-$dotnet_sdk_version-win-x86.zip; `
$dotnet_sha512 = '48aa1afaf7a52effb367bbb14a66e2c3bf8da468025795daf0fa0d18e3b9650ba3bd23800c9965a4d4ec1d891afecbce51b2487730f1b0d6040ee7cb73a15ec6'; `
if ((Get-FileHash dotnet.zip -Algorithm sha512).Hash -ne $dotnet_sha512) { `
Write-Host 'CHECKSUM VERIFICATION FAILED!'; `
exit 1; `
}; `
`
Expand-Archive dotnet.zip -DestinationPath dotnet; `
Remove-Item -Force dotnet.zip
# Install PowerShell global tool
RUN $powershell_version = '7.0.0'; `
Invoke-WebRequest -OutFile PowerShell.Windows.x64.$powershell_version.nupkg https://pwshtool.blob.core.windows.net/tool/$powershell_version/PowerShell.Windows.x64.$powershell_version.nupkg; `
$powershell_sha512 = '1980da63a4f6017235e7af810bfda66be8fa53d0475d147a8219a36c76a903af99adb6cd5309e3dadc610389ae3525bca1ca2d30e7a991640e924334fd4e4638'; `
if ((Get-FileHash PowerShell.Windows.x64.$powershell_version.nupkg -Algorithm sha512).Hash -ne $powershell_sha512) { `
Write-Host 'CHECKSUM VERIFICATION FAILED!'; `
exit 1; `
}; `
`
\dotnet\dotnet tool install --add-source . --tool-path \powershell --version $powershell_version PowerShell.Windows.x64; `
\dotnet\dotnet nuget locals all --clear; `
Remove-Item -Force PowerShell.Windows.x64.$powershell_version.nupkg; `
Remove-Item -Path \powershell\.store\powershell.windows.x64\$powershell_version\powershell.windows.x64\$powershell_version\powershell.windows.x64.$powershell_version.nupkg -Force
# SDK image
FROM mcr.microsoft.com/windows/servercore:1909
ENV `
# Enable detection of running in a container
DOTNET_RUNNING_IN_CONTAINER=true `
# Enable correct mode for dotnet watch (only mode supported in a container)
DOTNET_USE_POLLING_FILE_WATCHER=true `
# Skip extraction of XML docs - generally not useful within an image/container - helps performance
NUGET_XMLDOC_MODE=skip `
# PowerShell telemetry for docker image usage
POWERSHELL_DISTRIBUTION_CHANNEL=PSDocker-DotnetCoreSDK-NanoServer-1909
# In order to set system PATH, ContainerAdministrator must be used
USER ContainerAdministrator
RUN setx /M PATH "%PATH%;C:\Program Files (x86)\dotnet;C:\Program Files\powershell"
USER ContainerUser
COPY --from=installer ["/dotnet", "/Program Files (x86)/dotnet"]
COPY --from=installer ["/powershell", "/Program Files/powershell"]
# Trigger first run experience by running arbitrary cmd
RUN dotnet help
这样就可以正常构建,并且最后的
dotnet help
命令可以正确执行。我将应用程序Dockerfile更改为使用此自定义镜像作为基础镜像,并且它也可以很好地构建。当我从Visual Studio 2019运行此程序时,我收到与上面相同的错误(“无法启动程序:'C:\ Program Files \ dotnet \ dotnet.exe。”)。为什么VS仍在尝试使用x64入口点。该项目是针对x86平台构建的,生成的图像看起来不错。
我根据应用程序镜像和
CMD
创建了一个容器,并确认所有文件都在预期的位置,甚至从命令行运行dotnet applicationName.dll
,应用程序开始运行。当我尝试从Visual Studio运行时,它尝试通过以下方式运行图像:
docker run -dt -v "C:\Users\Valued Customer\onecoremsvsmon\16.5.0102.0:C:\remote_debugger:ro" -v "C:\Users\Valued Customer\AppData\Roaming\Microsoft\UserSecrets:C:\Users\ContainerUser\AppData\Roaming\Microsoft\UserSecrets:ro" -v "C:\Users\Valued Customer\AppData\Roaming\ASP.NET\Https:C:\Users\ContainerUser\AppData\Roaming\ASP.NET\Https:ro" -e "ASPNETCORE_URLS=https://+:443;http://+:80" -e "ASPNETCORE_ENVIRONMENT=Development" -e "ASPNETCORE_LOGGING__CONSOLE__DISABLECOLORS=true" -P --name WAPTCoreWebService_1 --entrypoint C:\remote_debugger\x64\msvsmon.exe waptcorewebservice /noauth /anyuser /silent /nostatus /noclrwarn /nosecuritywarn /nofirewallwarn /nowowwarn /fallbackloadremotemanagedpdbs /timeout:2147483646 /LogDebuggeeOutputToStdOut
入口点指向x64应用程序(msvsmon.exe)。这可能是从VS运行的问题吗?
最佳答案
这不是一个完美的答案,但是我确实设法获得了一个基于VC++ x86 DLL并在Azure Kubernetes Service上运行的x86 .NET Core Web API。基本上我分为三个阶段:
下面包括三个Dockerfile。接下来,我将寻求将其整合为单个Dockerfile。
添加C++ Redist x86:waptx86custom
请注意,我从自己的Azure帐户中提取了redist exe的副本,但是您也可以将其包含在与Dockerfile相同的文件夹中,然后从那里添加它。
FROM mcr.microsoft.com/windows/servercore:ltsc2019 AS base
# Installing Microsoft Visual C++ 2015 x86 Redistributable.
ADD https://lqsts.blob.core.windows.net/temp/vc_redist_2015_3.x86.exe C:/vc_redist.x86.exe
RUN C:\vc_redist.x86.exe /install /norestart /quiet /log vc_log.txt
添加.NET Core SDK x86:waptx86corecustom
# escape=`
# Installer image
FROM acswebwapt.azurecr.io/waptx86custom AS installer
# Apply latest patch
RUN curl -fSLo patch.msu http://download.windowsupdate.com/c/msdownload/update/software/updt/2020/01/windows10.0-kb4534119-x64_a2dce2c83c58ea57145e9069f403d4a5d4f98713.msu `
&& mkdir patch `
&& expand patch.msu patch -F:* `
&& del /F /Q patch.msu `
&& DISM /Online /Quiet /Add-Package /PackagePath:C:\patch\windows10.0-kb4534119-x64.cab `
&& rmdir /S /Q patch
ENV COMPLUS_NGenProtectedProcess_FeatureEnabled 0
RUN \Windows\Microsoft.NET\Framework64\v4.0.30319\ngen uninstall "Microsoft.Tpm.Commands, Version=10.0.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=amd64" `
&& \Windows\Microsoft.NET\Framework64\v4.0.30319\ngen update `
&& \Windows\Microsoft.NET\Framework\v4.0.30319\ngen update
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue'; $verbosePreference='Continue';"]
# Retrieve .NET Core SDK
RUN $dotnet_sdk_version = '3.1.201'; `
Invoke-WebRequest -OutFile dotnet.zip https://dotnetcli.azureedge.net/dotnet/Sdk/$dotnet_sdk_version/dotnet-sdk-$dotnet_sdk_version-win-x86.zip; `
$dotnet_sha512 = '48aa1afaf7a52effb367bbb14a66e2c3bf8da468025795daf0fa0d18e3b9650ba3bd23800c9965a4d4ec1d891afecbce51b2487730f1b0d6040ee7cb73a15ec6'; `
if ((Get-FileHash dotnet.zip -Algorithm sha512).Hash -ne $dotnet_sha512) { `
Write-Host 'CHECKSUM VERIFICATION FAILED!'; `
exit 1; `
}; `
`
Expand-Archive dotnet.zip -DestinationPath dotnet; `
Remove-Item -Force dotnet.zip
# Install PowerShell global tool
RUN $powershell_version = '7.0.0'; `
Invoke-WebRequest -OutFile PowerShell.Windows.x64.$powershell_version.nupkg https://pwshtool.blob.core.windows.net/tool/$powershell_version/PowerShell.Windows.x64.$powershell_version.nupkg; `
$powershell_sha512 = '1980da63a4f6017235e7af810bfda66be8fa53d0475d147a8219a36c76a903af99adb6cd5309e3dadc610389ae3525bca1ca2d30e7a991640e924334fd4e4638'; `
if ((Get-FileHash PowerShell.Windows.x64.$powershell_version.nupkg -Algorithm sha512).Hash -ne $powershell_sha512) { `
Write-Host 'CHECKSUM VERIFICATION FAILED!'; `
exit 1; `
}; `
`
\dotnet\dotnet tool install --add-source . --tool-path \powershell --version $powershell_version PowerShell.Windows.x64; `
\dotnet\dotnet nuget locals all --clear; `
Remove-Item -Force PowerShell.Windows.x64.$powershell_version.nupkg; `
Remove-Item -Path \powershell\.store\powershell.windows.x64\$powershell_version\powershell.windows.x64\$powershell_version\powershell.windows.x64.$powershell_version.nupkg -Force
# SDK image
FROM acswebwapt.azurecr.io/waptx86custom
ENV `
# Enable detection of running in a container
DOTNET_RUNNING_IN_CONTAINER=true `
ASPNETCORE_URLS=http://+:443;http://+:80 `
# Enable correct mode for dotnet watch (only mode supported in a container)
DOTNET_USE_POLLING_FILE_WATCHER=true `
# Skip extraction of XML docs - generally not useful within an image/container - helps performance
NUGET_XMLDOC_MODE=skip `
# PowerShell telemetry for docker image usage
POWERSHELL_DISTRIBUTION_CHANNEL=PSDocker-DotnetCoreSDK-NanoServer-1909
# In order to set system PATH, ContainerAdministrator must be used
USER ContainerAdministrator
RUN setx /M PATH "%PATH%;C:\Program Files (x86)\dotnet;C:\Program Files\powershell"
USER ContainerUser
COPY --from=installer ["/dotnet", "/Program Files (x86)/dotnet"]
COPY --from=installer ["/powershell", "/Program Files/powershell"]
# Trigger first run experience by running arbitrary cmd
RUN dotnet help
添加应用程序
FROM acswebwapt.azurecr.io/waptx86corecustom AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM acswebwapt.azurecr.io/waptx86corecustom AS build
WORKDIR /src
COPY ["WAPTCoreWebService/WAPTCoreWebService.csproj", "WAPTCoreWebService/"]
RUN dotnet restore "WAPTCoreWebService/WAPTCoreWebService.csproj"
COPY . .
WORKDIR "/src/WAPTCoreWebService"
RUN dotnet build "WAPTCoreWebService.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "WAPTCoreWebService.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "WAPTCoreWebService.dll"]
关于c# - 如何在Docker中运行.NET Core 3.1.3 x86 App,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/61491430/