【问题标题】:Create Docker Image of .NET Core 3.1 app on Windows 10 Pro and pull it to Windows Server 2016在 Windows 10 Pro 上创建 .NET Core 3.1 应用程序的 Docker 映像并将其拉到 Windows Server 2016
【发布时间】:2021-04-12 21:50:25
【问题描述】:

我已成功创建包含 .NET Core 3.1 项目的 Docker 映像,并在我的本地 Windows 10 Pro 机器上的 Windows 容器中运行它们。我使用的是 Windows 容器,而不是 Linux。

我希望能够将它们拉到 Windows 2016 Server 机器(不是 VM)。我在 Windows 2016 服务器上安装了 Docker EE,它正在运行。 docker 版本报告版本 20.10.0。

根据以下内容,没有任何可用于 Windows Server 2016 的受支持的 .NET Core 映像。no matching manifest for windows/amd64 Server 2016

如果这是真的,我是在尝试做一些不可能的事情吗?还是根本不支持?

我是新手,但据我了解,.NET Core 应用程序需要在主机中安装 nanoserver 1809 或更高版本。如果不正确,请告诉我...

注意:我已成功将其拉入 Windows 2016 Server:

docker pull mcr.microsoft.com/windows/nanoserver:sac2016

但从我在这里读到的内容来看,https://github.com/dotnet/dotnet-docker/issues/1041,.NET Core 3.x 在该基础上不再受支持。

第 1 期

当我在 Windows 2016 Server 上运行以下命令时,我收到错误“清单列表条目中没有 windows/amd64 10.0.14393 的匹配清单”。

docker pull mcr.microsoft.com/windows/nanoserver:1809

根据这个页面,我应该可以拉到:https://docs.microsoft.com/en-us/virtualization/windowscontainers/deploy-containers/deploy-containers-on-server

第 2 期

从我读到的内容看来,我需要创建我的图像,或者至少在容器中以“hyperv”隔离模式运行它们。正确的?或者 docker 主机本身可以运行不同版本的操作系统(如 nanoserver 1809 或其他)?我正在使用 Visual Studio 在本地构建所有这些,并且还使用 docker-compose,我可以在 yml 文件中指定隔离模式。但是当我通过 VS.NET 将图像发布到 Docker Hub 时,我不知道该怎么做。我的图像发布成功,但是当我尝试使用 docker pull 将它们下载到 Windows 2016 Server 时,我收到此错误:

a Windows version 10.0.19042-based image is incompatible with a 10.0.14393 host

第 3 期

与上述错误有关,我想我需要在我的映像中包含较旧的 Windows 基础版本?我在 dockerfile 中添加了以下内容:

FROM mcr.microsoft.com/windows/nanoserver:1809

但它似乎没有做任何事情。当我在 VS.NET 中运行项目时,我在检查容器时看到了这一点:

OsVersion: 10.3.19042.867

我的概念验证目标很简单:

  1. 在我的 Windows 10 Pro 笔记本电脑上创建 .NET Core 3.1 Web api 项目的映像
  2. 将其拉入 Windows 2016 Server 并在 Docker 容器中运行。

#1 都可以在我的笔记本电脑上运行。完成 #2 是我真正感到困惑的地方。

谢谢,布伦特

更新

以下是我用来构建映像、在容器中运行并检查它的 Dockerfile 和命令。请注意,使用此 Dockerfile,我现在可以在交互式命令提示符中看到:

  • 正确的操作系统版本:10.0.14393
  • 文件系统确实包含我的 .Net 解决方案、项目和源代码。

我刚刚获取了 MattT 提供的内容并将其添加到 VS.NET 在添加 DockerSupport 时生成的 Dockerfile 的开头。我知道我搞砸了我的 Dockerfile,因为它没有构建/发布或运行我的 webapi 项目(就像在添加新命令之前所做的那样)。我认为这与我的 FROM 语句有关。我读了很多,但还不明白分层是如何工作的。

# escape=`
FROM mcr.microsoft.com/windows/servercore:ltsc2016 AS baseOS
RUN powershell -Command [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12; $ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest -UseBasicParsing -Uri https://dot.net/v1/dotnet-install.ps1 -OutFile dotnet-install.ps1; ./dotnet-install.ps1 -InstallDir '/Program Files/dotnet' -Channel 3.1 -Runtime dotnet; Remove-Item -Force dotnet-install.ps1 && setx /M PATH "%PATH%;C:\Program Files\dotnet"
COPY . .

FROM mcr.microsoft.com/dotnet/aspnet:3.1 AS base

WORKDIR /app
EXPOSE 80
EXPOSE 8001

FROM mcr.microsoft.com/dotnet/sdk:3.1 AS build
WORKDIR /src
COPY ["WebApi.csproj", "."]

RUN dotnet restore "WebApi.csproj"
COPY . .

WORKDIR "/src/"
RUN dotnet build "WebApi.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "WebApi.csproj" -c Release -o /app/publish

FROM base AS final
#FROM baseOS AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "WebApi.dll"]

我运行的docker命令:

docker build -f "C:\Cabinet\Learning\EssApiProjects\src\Services\WebApi\Dockerfile" --force-rm -t webapi:ltsc2016 --target baseOS "C:\Cabinet\Learning\EssApiProjects\src\Services\WebApi"

docker run --env ASPNETCORE_ENVIRONMENT=Development -p 8001:80 --name webapi_ltsc2016 -it webapi:ltsc2016

docker exec -it webapi_ltsc2016 cmd.exe 

【问题讨论】:

    标签: docker .net-core


    【解决方案1】:

    支持的内容和可用的内容之间存在差异。支持在 Windows Server 2016 上的容器中运行 .NET Core,但没有可用的映像。您可以自己定义。

    您对哪些 Windows 容器版本可以在 Windows Server 2016 主机上运行的选项仅限于 Windows Server 2016 容器。例如,这意味着您不能在 Server 2016 主机上运行 nanoserver:1809 容器。这在Windows container version compatibility matrix 中有说明:

    请注意,nanoserver:sac2016 早已不受支持,因此它不是推荐的基础镜像。 Nano Server 2016 目前没有任何支持的标签。相反,建议使用 Windows Server Core。 servercore:ltsc2016 是受支持标签的最佳选择。

    以下是如何在 Server Core 映像上安装 .NET Core 的示例:

    # escape=`
    
    FROM mcr.microsoft.com/windows/servercore:ltsc2016
    RUN powershell -Command `
            $ErrorActionPreference = 'Stop'; `
            $ProgressPreference = 'SilentlyContinue'; `
            [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12;
            Invoke-WebRequest `
                -UseBasicParsing `
                -Uri https://dot.net/v1/dotnet-install.ps1 `
                -OutFile dotnet-install.ps1; `
            ./dotnet-install.ps1 `
                -InstallDir '/Program Files/dotnet' `
                -Channel 3.1 `
                -Runtime aspnetcore; `
            Remove-Item -Force dotnet-install.ps1 `
        && setx /M PATH "%PATH%;C:\Program Files\dotnet"
    

    更多资源:

    更新

    这是一个如何使用 Visual Studio 生成的 Dockerfile 定义的示例:

    # escape=`
    FROM mcr.microsoft.com/windows/servercore:ltsc2016 AS base
    
    # Install ASP.NET Core 3.1
    RUN powershell -Command `
            $ErrorActionPreference = 'Stop'; `
            $ProgressPreference = 'SilentlyContinue'; `
            [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12;
            Invoke-WebRequest `
                -UseBasicParsing `
                -Uri https://dot.net/v1/dotnet-install.ps1 `
                -OutFile dotnet-install.ps1; `
            ./dotnet-install.ps1 `
                -InstallDir '/Program Files/dotnet' `
                -Channel 3.1 `
                -Runtime aspnetcore; `
            Remove-Item -Force dotnet-install.ps1 `
        && setx /M PATH "%PATH%;C:\Program Files\dotnet"
    
    WORKDIR /app
    EXPOSE 80
    EXPOSE 8001
    
    FROM mcr.microsoft.com/windows/servercore:ltsc2016 AS build
    
    # Install .NET Core 3.1 SDK
    RUN powershell -Command `
            $ErrorActionPreference = 'Stop'; `
            $ProgressPreference = 'SilentlyContinue'; `
            [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12;
            Invoke-WebRequest `
                -UseBasicParsing `
                -Uri https://dot.net/v1/dotnet-install.ps1 `
                -OutFile dotnet-install.ps1; `
            ./dotnet-install.ps1 `
                -InstallDir '/Program Files/dotnet' `
                -Channel 3.1; `
            Remove-Item -Force dotnet-install.ps1 `
        && setx /M PATH "%PATH%;C:\Program Files\dotnet"
    
    WORKDIR /src
    COPY ["WebApi.csproj", "."]
    
    RUN dotnet restore "WebApi.csproj"
    COPY . .
    
    WORKDIR "/src/"
    RUN dotnet build "WebApi.csproj" -c Release -o /app/build
    
    FROM build AS publish
    RUN dotnet publish "WebApi.csproj" -c Release -o /app/publish
    
    FROM base AS final
    WORKDIR /app
    COPY --from=publish /app/publish .
    ENTRYPOINT ["dotnet", "WebApi.dll"]
    

    【讨论】:

    • 谢谢@Matt。我将你的命令添加到我的 Dockerfile 中(连同这个来解决 TLS 错误:[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12;),当我的 docker 构建成功时,检查图像仍显示操作系统版本 10.0.19042.867。我以为我的图像会有一个服务器核心操作系统......我不是要你回应,因为我显然还有很多学习要做。
    • 您是说您正在构建的 Dockerfile 是基于 servercore:ltsc2016 但是在检查容器时您看到它说它的版本是 10.0.19042.867?您能否提供您为构建 Dockerfile、运行容器和检索操作系统版本而执行的确切命令?
    • 非常感谢马特。我想我在上面发布的更新部分提供了您所要求的内容。回到阅读“Windows 上的 Docker - 第二版”……我在一周内学到了很多东西,但还不足以连接所有的点。
    • Matt,通过使用您给我的 dockerfile 创建一个图像并将其包含在我的 .NET 项目的 dockerfile 中(使用 FROM myimagename:tag 作为基础并注释掉 FROM ... aspnet:3.1作为基础)我能够创建具有正确操作系统的图像,并且它还构建了我的 DotNet 应用程序。但是当我尝试运行它时,我得到:找不到框架 Microsoft.AspNetCore.App 版本“3.1.0”。没有找到框架。当我以交互模式运行容器时 dotnet --info 报告:.NET Core runtimes installed: Microsoft.NETCore.App 3.1.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
    • 我更新了我的帖子以包含一个示例 VS Dockerfile,它在不同的阶段安装 ASP.NET Core 和 SDK。
    猜你喜欢
    • 2019-03-25
    • 2019-01-02
    • 2018-11-27
    • 2016-10-24
    • 2020-10-18
    • 2017-08-04
    • 2021-12-26
    • 1970-01-01
    相关资源
    最近更新 更多