Docker 在多个图层中有相同的文件

Docker have the same file in multiple layers

通常的做法是提前复制 package.jsonrequirements.txt 以利用 Docker 缓存并防止每次源更改时安装依赖项:

# Install python dependencies
COPY requirements.txt .
RUN pip install -r requirements.txt

# Copy sources and models
COPY . .

COPY 命令应该只复制更改的文件。但是,如果在一个Docker文件中出现多次COPY,同一个文件突然出现在多层中。所以最终图像更大。我使用相同的技术预复制一个 7GB 的文件。遗憾的是,我的最终图像有 14GB,因为这个文件存在于两层中。

要模拟该问题,请创建一个包含一些虚拟内容的文本文件 a.txt。使用 .dockerignore 不复制 Dockerfile.dockerignore。然后使用以下 Docker 文件构建图像:

FROM alpine
COPY a.txt .
COPY . .
CMD ["ls", "-la"]

构建后,使用docker image history image-name检查大小。文件 a.txt (4B) 被错误地包含在 2 层中。

IMAGE          CREATED         CREATED BY                                      SIZE      COMMENT
9fd840bc8435   5 seconds ago   CMD ["ls" "-la"]                                0B        buildkit.dockerfile.v0
<missing>      5 seconds ago   COPY . . # buildkit                             4B        buildkit.dockerfile.v0
<missing>      6 minutes ago   COPY a.txt . # buildkit                         4B        buildkit.dockerfile.v0
<missing>      7 weeks ago     /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B        
<missing>      7 weeks ago     /bin/sh -c #(nop) ADD file:9233f6f2237d79659…   5.59MB 

先复制 package.json 之类的文件,然后再复制所有文件的模式是为了支持您经常构建并希望最大程度地缩短该过程所需时间的开发过程。

如果您还有其他需要优先考虑的问题,没有理由不这样做。

例如,如果您经常构建,您的 Dockerfile 可能如下所示

FROM alpine
WORKDIR /app
COPY a.txt .
COPY . .
CMD ["ls", "-la"]

如果你想最小化最终图像的大小,你可以创建另一个 Dockerfile,它在像这样的单个操作中从该图像复制所有内容

FROM my-build-image as build
FROM alpine as final
COPY --from=build /app /app

我认为,拥有一个在构建大量时既快速又最大限度地减少space使用的 Dockerfile 是不可行的。