使用 Docker 构建时出现“程序不包含适用于入口点的静态 'Main' 方法”错误,原因是什么?

54

我在使用Docker时遇到了问题,并且找不到合适的解决方案。

我正在尝试使用.NET SDK 2.1构建Docker镜像。

问题是当Docker尝试运行构建语句时,它会失败并输出以下错误:

CSC : error CS5001: Program does not contain a static 'Main' method suitable for an entry point

有趣的是,如果我在本地命令行上执行构建语句,它就正常工作。

我已经检查了项目中的LanguageVersion标记,它是7.3。

这是我的Docker文件:

FROM microsoft/dotnet:2.1-sdk AS builder  
WORKDIR /src
COPY ./nuget  ./nuget
COPY ./NuGet.Config ./
COPY Services/AadTracking ./

# Copy all the referenced projects

COPY ./Services/AadTracking/Company/Company.Service.AadTracking/Company.Service.AadTracking.csproj ./AadTracking/Company/Company.Service.AadTracking/Company.Service.AadTracking.csproj
COPY ./Services/AadTracking/Office.Re.Service.AadTracking/Office.Re.Service.AadTracking.csproj ./AadTracking/Office.Re.Service.AadTracking/Office.Re.Service.AadTracking.csproj
COPY ./Services/AadTracking/Company/Office.Re.Service.AadTracking.Company/Office.Re.Service.AadTracking.Company.csproj ./AadTracking/Company/Office.Re.Service.AadTracking.Company/Office.Re.Service.AadTracking.Company.csproj
COPY ./Services/AadTracking/Office.Re.Service.AadTracking.EventStore/Office.Re.Service.AadTracking.EventStore.csproj ./AadTracking/Office.Re.Service.AadTracking.EventStore/Office.Re.Service.AadTracking.EventStore.csproj

# Restore packages
RUN dotnet restore "./AadTracking/Company/Company.Service.AadTracking/Company.Service.AadTracking.csproj"

RUN dotnet build -c Debug --no-restore "./AadTracking/Company/Company.Service.AadTracking/Company.Service.AadTracking.csproj"

# COPY source code 
#aad tracking
COPY ./Services/AadTracking/Company/Company.Service.AadTracking ./AadTracking/Company/Company.Service.AadTracking/
COPY ./Services/AadTracking/Office.Re.Service.AadTracking ./AadTracking/Office.Re.Service.AadTracking/
COPY ./Services/AadTracking/Company/Office.Re.Service.AadTracking.Company ./AadTracking/Company/Office.Re.Service.AadTracking.Company/
COPY ./Services/AadTracking/Office.Re.Service.AadTracking.EventStore ./AadTracking/Office.Re.Service.AadTracking.EventStore/

# Publish
RUN dotnet publish "./AadTracking/Company/Company.Service.AadTracking/Company.Service.AadTracking.csproj" -c Debug -o "../../dist"

# #Build the app image
FROM microsoft/dotnet:2.1-aspnetcore-runtime  
WORKDIR /app  

ENV ASPNETCORE_ENVIRONMENT Switch
ENV REINSURANCE_INSTANCE Docker-dev 

COPY --from=builder /dist .  

ENTRYPOINT ["dotnet", "Company.Service.AadTracking.dll"]

谢谢你的帮助!

12个回答

100

我知道回答有点晚了。不过,VS 2019 在 .NET Core 3.1 中仍存在相同问题。我查看了微软提供的示例,发现 Docker 文件存放在解决方案中的不同位置,而 Docker 复制命令无法正常工作。

你需要将您的 Docker 文件向上移动一个目录,以便它们与 sln 文件处于相同级别。这将解决该问题。

或者,你可以像下面的示例 Docker 文件一样更改路径,而无需更改 Docker 文件位置。我认为最好将 Docker 文件与其他文件放在一起。

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim-arm64v8 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
COPY ["WhatzThat.Web.csproj", "WhatzThat.Web/"]
RUN dotnet restore "WhatzThat.Web/WhatzThat.Web.csproj" -r linux-arm64

WORKDIR "/src/WhatzThat.Web"
COPY . .

RUN dotnet build "WhatzThat.Web.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "WhatzThat.Web.csproj" -c Release -o /app/publish -r linux-arm64 --self-contained false --no-restore

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

29
我曾经为此苦苦挣扎,在这个问题上,我按照答案中的正确建议进行了大多数路径调整。结果发现,导致我的构建步骤失败的一个原因是在恢复之后的 WORKDIR 命令之前,我使用了 COPY . . 命令。一旦我纠正了这个错误,我的构建步骤就成功了。感谢你的帮助,希望我的额外提示也能对其他人有所帮助。 - CoderSivu
1
不清楚路径的更改是什么。可以详细说明一下吗? - Nico
1
为什么微软会做这样愚蠢的事情!感谢您的回答。 - beast
2
@CoderSivu,这对我也解决了问题。想象一下我认为我可以信任微软从VS2022提供正确的自动生成模板Dockerfiles... - Michael Harris
3
除了在第一个“copy”中删减项目文件夹路径之外,将“workdir”命令移到“copy . .”之前确实是解决方案的关键部分。原始问题在于,我认为它确实是为了从解决方案文件夹运行而编写的,“COPY . .”将所有项目文件夹复制到src/(毫无意义 - 似乎是修复另一个错误的错误)。我只能使用“docker build -t myImage -f myProject\Dockerfile .”按照原样运行它。 - Josh Sutterfield
显示剩余4条评论

30

2023年更新

很遗憾,Microsoft在Dockerfile中包括的内容与运行它的目录存在不一致。

有三种解决方案可供选择。

第一种解决方案

  1. 将生成的Dockerfile与.sln文件放在同一级别。

  2. 从解决方案的根目录运行以下命令

    docker build -t imagename .


第二种解决方案

  1. 将Dockerfile保留在项目文件夹内。

  2. 从解决方案的根目录运行以下命令

    docker build -t imagename -f .\SampleProject\Dockerfile .


第三种解决方案

对Dockerfile进行小改动。现在您必须从项目文件夹(.sln文件下一级)运行docker命令。

将以下更改:

enter image description here

更改为:

enter image description here

补充说明

enter image description here


3
第三个解决方案是一个很好的例子!对我有用,谢谢。 - Ramil Aliyev 007
@RamilAliyev 如果它对你有用,你不考虑点赞吗? - Omer
谢谢。我自己找到了第三个解决方案,只是错过了最后一部分,你需要交换WORKDIR和COPY命令。不确定为什么需要这样做,但无论如何,现在也无所谓了。 - Brad Firesheets
谢谢!有人可以解释一下COPY和WORKDIR吗?我弄清楚了其他部分,但不明白这个。 - undefined

21

我遇到了同样的问题。
我发现我的Docker文件与我的.csproj文件处于相同的级别。我将我的Docker文件移动到文件夹结构中的上一层,现在可以正常构建。


1
明白了,谢谢!但是这样VS就无法构建和调试项目了。 - Nikita Danilov
天啊,我遇到了同样的问题,浪费了半天时间进行调试。谢谢! - Anindhito Irmandharu

13
使用多项目解决方案结构,我通过将“src”再次添加到目录中来进行修复。
类似于这样:
COPY ["src/Todo.Core/Todo.Core.csproj", "Todo.Core/"]
RUN dotnet restore "Todo.Api/Todo.Api.csproj"
COPY . .
WORKDIR "/src/Todo.Api/"
RUN dotnet build "Todo.Api.csproj" -c Release -o /app/build

变成了这个:

COPY ["src/Todo.Core/Todo.Core.csproj", "Todo.Core/"]
RUN dotnet restore "Todo.Api/Todo.Api.csproj"
COPY . .
WORKDIR "/src/src/Todo.Api/"
RUN dotnet build "Todo.Api.csproj" -c Release -o /app/build

这对我起了作用,谢谢!!! - Dvd Franco
你真是个救命恩人,这个答案应该排得更靠前!谢谢! - Guido Spadavecchia
那个黑暗的魔法奏效了!但我不明白为什么会这样。我在开头设置了一个工作目录为/src,然后将本地src/project复制到project中。 - Bruno Casarotti
我简直不敢相信我在这上面浪费了几个小时。 - Henry Rodriguez

13

在 Docker 中编译和发布应用程序需要将整个应用程序复制到 Docker 中。

这意味着您需要将所有类文件(.cs)以及所需的支持文件(可能是 resx 或配置文件)复制到 Docker 中。

请参考以下内容:

https://github.com/aspnet/aspnet-docker/issues/401


嗯,这一行不是将整个文件夹复制到Docker吗?COPY Services/AadTracking ./ 在下面的行中,我还复制了csproj文件。 - Van Darth Vadden
1
是的,它将从Services/AadTracking复制所有文件到./,但由于您正在显式地复制csproj并将其原始位置更改为AadTracking文件夹内部,因此它会丢失对.cs文件的引用。 尝试在本地执行相同的操作...按照命令中提到的方式复制文件,然后尝试使用dotnet build命令..问题将再现。 - RakeshPawar

3

对我而言,在dotnet build命令之前,COPY..是在workdir之后。我只需将其放在workdir命令之后即可,然后它就可以工作了。

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

3

我的 DockerFile 放在根目录而不是上层目录,并且我将 DockerFile 更改为:

#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.

#Depending on the operating system of the host machines(s) that will build or run the containers, the image specified in the FROM statement may need to be changed.
#For more information, please see https://aka.ms/containercompat

FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /src
COPY ["projectName.csproj", "projectName/"]
RUN dotnet restore "projectName/projectName.csproj"

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

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

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


2

marvelTracker的答案对我有用,但在Visual Studio 2022内置的Docker工具中使用它会出现问题。

在项目文件夹中使用命令docker build -f Dockerfile ..会从父文件夹的角度构建dockerfile。

Microsoft文档解释了在VS2022中构建Docker的方法:https://learn.microsoft.com/en-us/visualstudio/containers/container-build?view=vs-2022

注意:我在为.NET 6 Docker项目解决相同错误时发现了这个方法。

希望这能帮助其他人。


2

我有一个错误的理由。

我的Docker文件……我正确地复制了目录结构和.sln和.csproj文件……

但是在复制源文件时,我有语法错误。(.cs文件等)

#糟糕!

如果你看一下上面的问题,基本上我在OP下面的步骤中有一个语法错误/bug:

# COPY source code

更重要的是,我是怎样发现这个问题的?下面给你解释一下:
docker images

当你不想进入最后一个(也就是失败的镜像),而是想要进入倒数第二个镜像时,可以使用以下方法。请注意,Docker会为Docker文件中的每个步骤创建新的镜像。

docker images

REPOSITORY           TAG                 IMAGE ID            CREATED             SIZE
mything1/mything2    latest              aaaaaaaaaaaa        27 minutes ago      271MB
<none>               <none>              bbbbbbbbbbbb        27 minutes ago      1.18GB

然后深入(倒数第二个)

docker run --rm -it bbbbbbbbbbbb  sh  

当你进入那里时,开始使用“ls”和“cd”命令。

我发现我的.cs源文件没有放在正确的位置。经过一些修复相对路径问题(在我的特定情况下)后......我的源文件放在了正确的位置。#好棒

这是一个非常通用的提示,用于调试运行失败的图像。


1

这个错误意味着包含Main方法的文件未被包含,因此您可能忘记将其复制到正确的目录中,或者Docker指向了错误的目录。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接