1

我正在从这个 .NET Core 应用程序创建一个 Docker 容器,该应用程序在解决方案中有多个项目,我想知道将COPY每个项目文件分开还是一行更好。

Visual Studio 生成一个 Dockerfile,它将每个项目文件复制到新的一行,如下所示:

WORKDIR /src
COPY Dir1/Dir1.csproj Dir1/
COPY Dir2/Dir2.csproj Dir2/
COPY Dir3/Dir4/Dir4.csproj Dir3/Dir4/
RUN dotnet restore Dir1/Dir1.csproj

但是,使用 Docker 创建 .NET 应用程序的 Microsoft文档显示为仅使用单个COPY语句的“优化”,如下所示:

WORKDIR /src
COPY . .
RUN dotnet restore Dir1/Dir1.csproj

据说,根据我对文章的理解,创建一个更大的图像,但COPY如果一个项目发生变化,则不必对所有其他项目。

有趣的是,Docker 文档提到

COPY它们是单独的,而不是一次性的。这确保了每个步骤的构建缓存仅在特定需要的文件发生更改时才失效(强制重新运行该步骤)。

这基本上与微软文章所说的相矛盾,即COPY当一个项目发生变化时必须重新运行该步骤。

我想知道哪个选项更好,为什么,或者出于什么目的。或者我可能误解了一些文档,那么请向我解释其中的区别。

4

1 回答 1

2

IMO 的最佳实践方法是将每个项目复制为一个单独的层,即一个专门的COPY声明。

使用分离层。

  1. 更快 的构建:docker 正在缓存层,所以如果你在一个项目中进行了更改 - 下次构建图像​​时,docker 将只构建更改的层并为其他层使用缓存。
  2. 更快的部署:层可以并行拉
  3. 高效托管:得益于 docker copy on write机制,可以跨镜像共享层以节省空间和 IO:

Copy-on-write 是一种共享和复制文件以实现最大效率的策略。如果一个文件或目录存在于镜像中的较低层,并且另一个层(包括可写层)需要对其进行读取访问,则它只使用现有文件。其他层第一次需要修改文件时(构建镜像或运行容器时),文件被复制到该层并修改。这最大限度地减少了 I/O 和每个后续层的大小

您在 Dockerfiles 中看到通用COPY . .语句的原因是因为通常 dockerfile 包含一个项目,这也是我想针对您的情况推荐的最佳实践 - 在每个项目中放置一个 dockerfile 并构建单独的图像(在公共基础图像)。

如果您应该将所有项目托管在一个图像中,至少将它们复制为不同的层。

于 2019-07-23T07:05:12.547 回答