构建时如何调试 docker-compose 缓存未命中

use*_*014 6 docker docker-compose

我正在执行相同的docker-compose build命令,我发现它错过了缓存

Building service1
Step 1/31 : FROM node:10 as build-stage
 ---> a7366e5a78b2
Step 2/31 : WORKDIR /app
 ---> Using cache
 ---> 8a744e522376
Step 3/31 : COPY package.json yarn.lock ./
 ---> Using cache
 ---> 66c9bb64a364
Step 4/31 : RUN yarn install --production
 ---> Running in 707365c332e7
yarn install v1.21.1
..
..
..
Run Code Online (Sandbox Code Playgroud)

如您所见,缓存已丢失,但我不明白为什么 调试更改并尝试找出原因的最佳方法是什么

编辑:问题不是调试我的具体问题。但是我一般如何调试这种问题。我怎么知道为什么 docker-compose 认为事情发生了变化(尽管我很确定没有任何变化),哪些文件/命令/结果不同?

Von*_*onC 3

我通常如何调试此类问题。我怎么知道为什么 docker-compose 认为事情发生了变化(尽管我很确定什么都没有改变),哪些文件/命令/结果是不同的

一般来说,如下所示

我有点沮丧,因为我似乎找不到任何方法让 Docker 构建更详细

但是当涉及到docker-compose时,这取决于您使用的版本和选项。
moby/moby第 30081 期解释(作者:Sebastiaan van Stijn ( thaJeztah))

docker-compose和的当前版本docker build在许多(或所有)情况下不会共享构建缓存,或者至少不会生成相同的摘要。

原因是,当使用 发送构建上下文时docker-compose,它将使用略有不同的压缩(docker-compose用 Python 编写,而dockercli 是用 Go 编写的)。
由于它们是不同的实现(和语言),可能存在其他差异。

(这也在docker/compose 问题 883中讨论过)

的下一个版本docker compose将具有(当前选择加入)功能,使其使用实际的dockercli 来执行构建(通过设置COMPOSE_DOCKER_CLI_BUILD=1环境变量)。这是在docker/compose#6865中实现的(1.25.0-rc3+,2019 年 10 月)

有了这个功能,docker compose 还可以使用BuildKit来构建镜像(设置DOCKER_BUILDKIT=1环境变量)。
如果可能的话,我强烈建议您使用 buildkit 进行构建
使用 BuildKit(需要 Docker 18.09 或更高版本,目前不支持构建 Windows 容器)时,您将看到构建速度以及在重复构建中将构建上下文发送到守护进程所需的持续时间有了巨大的改进(buildkit 使用交互式会话仅发送构建期间所需的文件,而不是上传整个构建上下文)。

因此,首先仔细检查您的 docker-compose 是否使用 BuildKit,如果问题(缓存未重用)仍然存在,则:

COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker-compose build
Run Code Online (Sandbox Code Playgroud)

Sebastiaan 在第 4012 期中添加:

BuildKit 仍然是可选的(因为还没有 Windows 支持),但具有生产质量,并且可以用作构建 Linux 映像的默认设置。

最后,我意识到,对于 Azure 管道,您(可能)无法控制安装的 Docker 和 Docker Compose 的版本,但对于本地计算机,请确保更新到最新的 19.03 补丁版本;例如,Docker 19.03.3 及更高版本在 BuildKit 的缓存机制中进行了各种改进和修复(请参见docker#373)。


请注意,在您的特定情况下,即使这不是您问题中的主要问题,但了解以下内容是否有帮助会很有趣:

yarnpkg/yarn/issue 749建议:

您不会挂载 Yarn 缓存目录。相反,您应该确保利用 Docker 的镜像层缓存。

这些是我正在使用的命令:

COPY package.json yarn.lock ./
RUN yarn --pure-lockfile
Run Code Online (Sandbox Code Playgroud)

然后尝试你的yarn install命令,看看 docker 是否仍然不使用它的缓存。

RUN yarn install --frozen-lockfile --production && yarn cache clean 
Run Code Online (Sandbox Code Playgroud)

不要忘记 ayarn cache clean防止纱线缓存在 docker 层中缠绕

如果问题仍然存在,请直接切换到 buildkit(用于测试),使用 abuildctl build --progress=plain查看更详细的输出,并调试缓存情况。


通常,如下所示的多阶段方法可能很有用:

FROM node:alpine
WORKDIR /usr/src/app
COPY . /usr/src/app/

# We don't need to do this cache clean, I guess it wastes time / saves space: https://github.com/yarnpkg/rfcs/pull/53
RUN set -ex; \
  yarn install --frozen-lockfile --production; \
  yarn cache clean; \
  yarn run build

FROM nginx:alpine
WORKDIR /usr/share/nginx/html
COPY --from=0 /usr/src/app/build/ /usr/share/nginx/html
Run Code Online (Sandbox Code Playgroud)

正如nairum评论中指出的那样:

cache_from我刚刚发现,当我将多阶段 Dockerfile 与 Docker Compose 一起使用时,需要使用它来使缓存正常工作。

从文档中:

cache_from定义图像构建器应该用于缓存解析的源列表。

缓存位置语法必须遵循全局格式[NAME|type=TYPE[,KEY=VALUE]]
SimpleNAME实际上是 的快捷表示法type=registry,ref=NAME

COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker-compose build
Run Code Online (Sandbox Code Playgroud)