简体   繁体   中英

Create Docker Image of .NET Core 3.1 app on Windows 10 Pro and pull it to Windows Server 2016

I have successfully created Docker images that contain .NET Core 3.1 projects and am running them in Windows Containers on my local Windows 10 Pro machine. I am using Windows Containers, not Linux.

I want to be able to pull them to a Windows 2016 Server machine (not a VM). I have Docker EE installed on the Windows 2016 Server and it is running. docker version reports Version 20.10.0.

According to the following, there are not any supported .NET Core images available for Windows Server 2016. no matching manifest for windows/amd64 Server 2016

If that is true, am I trying to do something that is impossible? Or simply not supported?

I am new at this, but from what I understand .NET Core apps require nanoserver 1809 or higher to be installed in the host. If that is incorrect, let me know...

NOTE: I have successfully pulled this to the Windows 2016 Server:

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

But from what I read here, https://github.com/dotnet/dotnet-docker/issues/1041 , .NET Core 3.x is no longer supported on that base.

ISSUE 1

When I run the following on the Windows 2016 Server, I get the error "no matching manifest for windows/amd64 10.0.14393 in the manifest list entries".

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

According to this page, I should be able to pull that: https://docs.microsoft.com/en-us/virtualization/windowscontainers/deploy-containers/deploy-containers-on-server

ISSUE 2

From what I read it looks like I will need to create my images or at least run them in containers in "hyperv" isolation mode. Correct? Or can the docker host itself run a different version of the OS (like nanoserver 1809 or whatever)? I'm using Visual Studio to build all of this locally and am also using docker-compose where I can specify the isolation mode in the yml file. But I don't know how to do that when I publish my images to my Docker Hub through VS.NET. My images publish successfully, but then when I try to use docker pull to bring them down to the Windows 2016 Server I get this error:

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

ISSUE 3

Related to the above error, I guess I need to include an older Windows base version in my image? I have added the following to my dockerfile:

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

But it didn't seem to do anything. When I run the project in VS.NET, I see this when I inspect the container:

OsVersion: 10.3.19042.867

My goal for a proof of concept is simply to:

  1. Create an image of a .NET Core 3.1 web api project on my Windows 10 Pro laptop
  2. Pull it to a Windows 2016 Server and run it in a Docker Container.

#1 all works on my laptop. Getting #2 accomplished is where I'm really confused.

Thanks, Brent

UPDATE

Below are the Dockerfile and commands I use to build the image, run it in a container and inspect it. NOTE that with this Dockerfile, in the interactive command prompt I do now see:

  • the correct OS ver: 10.0.14393
  • the file system does contain my.Net solution, project and my source code.

I've just taken what MattT provided and added it to the beginning of the Dockerfile that VS.NET generated when I added DockerSupport. I know I have goofed my Dockerfile up because it doesn't build / publish or run my webapi project (as it did prior to adding the new commands). I assume it has something to do with my FROM statements. I've read so much, but don't yet understand how layering works, among other things.

# 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 commands I run:

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 

There's a difference between what is supported and what is available. Running .NET Core in a container on Windows Server 2016 is supported but there is not an available image for it. You're left to define your own.

Your options for what Windows container versions can run on a Windows Server 2016 host are limited to only Windows Server 2016 containers. This means you cannot run a nanoserver:1809 container on a Server 2016 host, for example. This is illustrated in the Windows container version compatibility matrix :

在此处输入图像描述

Note that nanoserver:sac2016 has long been out of support so it would not be a recommended base image. There is not any currently supported tag for Nano Server on 2016. Instead, it'd be recommended to use Windows Server Core. The servercore:ltsc2016 is your best option for a supported tag.

Here's an example of how you would install .NET Core on a Server Core image:

# 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"

Further resources:

UPDATE

Here's an example of how this would be defined using a Dockerfile generated by Visual Studio:

# 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"]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM