自动生成的 Dockerfile 用于 Web .NET Core 应用程序

3
在我看来,自动生成的用于Web .net core应用程序的Dockerfile太大了,但为什么?为什么微软决定这样创建它?
当我们在应用程序创建过程中添加“添加docker支持”标志时,将生成如下Dockerfile:
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster AS build
WORKDIR /src
COPY ["app/app.csproj", "app/"]
RUN dotnet restore "app/app.csproj"
COPY . .
WORKDIR "/src/app"
RUN dotnet build "app.csproj" -c Release -o /app/build

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

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

在我看来,它可以是这个样子:

FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster as build
WORKDIR /src
COPY ["app/app.csproj", "app/"]
RUN dotnet restore "app/app.csproj"
COPY . .
WORKDIR "/src/app"
RUN dotnet build "app.csproj" -c Release -o /app/build
RUN dotnet publish "app.csproj" -c Release -o /app/publish

FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim
WORKDIR /app
EXPOSE 80
EXPOSE 443
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "app.dll"]

为什么Microsoft决定首先获取aspnet:3.0-buster-slim来公开端口并将其后续用作最终结果呢?这样做似乎很麻烦,只需像我的示例中一样将此图像作为最后一步即可。另外,我们是否需要双重From来获取sdk:3.0-buster(第一个名称为build,第二个名称为publish)?可以像我的示例中一样逐个添加多个RUN步骤。
也许有一些技术建议解释为什么他们要这样做呢?
谢谢!

Dockerfile 中的第一张图片是 VS 用于调试的图片(按照惯例,有一个设置可以覆盖此设置并在 VS 2019 中使用特定命名阶段)。显然,您希望尽可能缩短和加快此过程的时间。 - Jeroen Mostert
2个回答

1
一个 Dockerfile 是由 docker build . 命令使用的一系列步骤。至少需要三个步骤:
FROM some-base-image
COPY some-code-or-local-content
CMD the-entrypoint-command

随着我们的应用程序变得越来越复杂,需要添加额外的步骤。例如恢复软件包和依赖项。以下命令可用于执行此操作:
RUN dotnet restore 

-or-

RUN npm install

或类似的情况。随着难度的增加,图像构建时间将增加,图像大小本身也将增加。

Docker构建步骤生成多个Docker镜像并缓存它们。请注意以下输出:

$ docker build .
Sending build context to Docker daemon  310.7MB
Step 1/9 : FROM node:alpine
 ---> 4c6406de22fd
Step 2/9 : WORKDIR /app
 ---> Using cache
 ---> a6d9fba502f3
Step 3/9 : COPY ./package.json ./
 ---> dc39d95064cf
Step 4/9 : RUN npm install
 ---> Running in 7ccc864c268c 

注意如何在步骤2中显示使用缓存,因为Docker意识到从第二步开始的所有内容与上一次构建步骤相同,可以安全地使用来自先前构建命令的缓存。
此模板的重点之一是构建高效的映像。可以通过两种方式实现效率:
1.减少构建映像所需的时间 2.减小最终映像的大小
对于#1,利用来自先前构建的缓存映像。将Dockerfile分成更多依赖于先前构建的部分可以加快构建过程。仅当Dockerfile编写有效时才可能依赖于缓存。
通过分离这些构建和发布阶段,docker build .命令将能够更好地使用来自Docker文件中先前步骤的更多缓存。
对于#2,请避免安装不需要的软件包,例如。
有关详细信息,请参阅Docker文档here

0

默认情况下,VisualStudio使用快速模式构建,实际上是在本地计算机上构建您的项目,然后使用卷挂载将输出文件夹共享到容器中。

在快速模式下,Visual Studio调用docker build并带有一个参数,告诉Docker仅构建基础阶段。Visual Studio处理其余的过程,而不考虑Dockerfile的内容。因此,当您修改Dockerfile时,例如自定义容器环境或安装其他依赖项时,应将修改放在第一阶段。放置在Dockerfile的构建、发布或最终阶段的任何自定义步骤都不会被执行。

因此,回答您的问题:

为什么Microsoft首先获取aspnet:3.0-buster-slim只是为了公开端口,并稍后将它们用作最终端口?

这是为了在VisualStudio中提供优化的快速模式构建和调试。


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