Dockerfile中针对ASP.NET的COPY . .命令

13

Visual Studio的Docker工具会为包含COPY . .命令的ASP.NET项目创建一个Dockerfile,如下所示:

Visual Studio的Docker工具将为包含COPY . .命令的ASP.NET项目创建一个Dockerfile,如下所示:

WORKDIR /src
COPY *.sln ./
...
COPY . .

从我所了解的情况来看,<src>参数是相对于上下文而言的,因此不会受到WORKDIR /src命令的影响。然而,<dest>相对于WORKDIR,因此会指向/src

这个命令只是将剩余的文件(docker-compose.yml、.dockerignore等)从根目录中带到包中吗?如果是这样的话,为什么要在RUN dotnet build...命令之前这样做呢?

下面是完整的Dockerfile:

FROM microsoft/aspnetcore:2.0 AS base
WORKDIR /app
EXPOSE 80

FROM microsoft/aspnetcore-build:2.0 AS build
WORKDIR /src
COPY *.sln ./
COPY MyProject/MyProject.csproj MyProject/
RUN dotnet restore
COPY . . # The line mentioned above
WORKDIR /src/MyProject
RUN dotnet build -c Release -o /app

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

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

18

COPY . . 命令会递归地将整个项目复制到构建容器中。

第1个和第2个 COPY 命令之间加上了 dotnet restore,然后再用 dotnet build 进行完全的 COPY . .,这是一种 Docker 缓存技巧,可以加速容器镜像的构建。采用这种方式是为了不必在每次修改代码时重新安装项目依赖项。

Docker 镜像是由多层组成的。Docker 比较每个新层所包含的内容和指令与先前构建的内容和指令是否匹配。如果匹配,则可跳过该层的构建步骤。

代码更改比依赖关系更频繁,而且通常从较慢的网络获取依赖项。如果在完成依赖项安装后再复制代码,则不会破坏每个其他更改的缓存依赖关系层。

这是许多带有依赖项管理器的语言的共同主题。例如 Go、Python、Node.js 等。相应的 Node.js 命令会先执行 package.jsonpackage-lock.json,然后才是应用程序的其余内容:

WORKDIR /app
COPY package.json package-lock.json /app/
RUN npm install
COPY . /app/
CMD ["node", "app/index.js"]

2
如果从 Visual Studio 生成的 Docker 文件有注释,那肯定会很有帮助!一开始这非常令人困惑,所有的教程都没有详细解释,只是期望你能理解。COPY . . 跳过已经存在的文件是很重要的。 - Simon_Weaver

5

以下是 Scott Hanselman 在上述内容方面提出的一些建议:

https://www.hanselman.com/blog/OptimizingASPNETCoreDockerImageSizes.aspx

专业提示:Docker 能够智能地生成中间镜像,尽可能减少工作量,但如果我们(开发者)也做正确的事情以帮助 Docker,那么它将非常有用。

例如,请看我们复制 .csproj 然后执行 "dotnet restore" 的地方。通常你会看到有些人会执行 "COPY . ." 然后进行还原。这样做不允许 Docker 检测到哪些内容已更改,每次构建都要重新还原。

通过将这个步骤分为两个步骤-复制项目、还原、复制代码,这意味着你的 "dotnet restore" 中间步骤将被 Docker 缓存,速度会快得多。


3
第一个点是“我现在的位置”,因此它将从与dockerfile相同的位置复制所有内容到容器中的“我现在的位置”。
在镜像/容器中,“我现在的位置”由https://docs.docker.com/engine/reference/builder/#workdir 433定义。
因此,如果您设置:
WORKDIR /tmp 并执行
COPY . .
它将把当前文件夹中的所有内容复制到/tmp。

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