给定:我想构建一个Dockerfile来编译Scala应用程序。为了加速构建,我希望缓存依赖项下载。
问题:由于某种原因,未缓存命令./sbt -sbt-dir ./sbt-dir -ivy ./ivy update
。
FROM openjdk:8 as workspace
ARG BUILD_VERSION
WORKDIR /build
COPY ./sbt ./sbt
COPY ./sbt-dist ./sbt-dist
COPY ./build.sbt ./build.sbt
COPY ./project/build.properties ./project/build.properties
COPY ./project/plugins.sbt ./project/plugins.sbt
RUN ./sbt -sbt-dir ./sbt-dir -ivy ./ivy update
COPY ./ ./
# Embedded postgres need to be run as non-root user
RUN useradd -ms /bin/bash runner
RUN chown -R runner /build
USER runner
RUN ./sbt -sbt-dir ./sbt-dir -ivy ./ivy clean test
RUN ./sbt -sbt-dir ./sbt-dir -ivy ./ivy docker:stage -Ddocker.image.version="${BUILD_VERSION}"
因为这个版本在新VM中运行所以我一直按下工作区图像并在下次运行时将其拉出来从中构建缓存
docker build --rm=false --cache-from=workspace --build-arg BUILD_VERSION=1 -t workspace .
这是一段输出
Step 2/22 : ARG BUILD_VERSION
---> Using cache
---> de98ffcfad8e
Step 3/22 : WORKDIR /build
---> Using cache
---> 253b71142240
Step 4/22 : COPY ./sbt ./sbt
---> Using cache
---> 3091fa1e1821
Step 5/22 : COPY ./sbt-dist ./sbt-dist
---> Using cache
---> f9c68659cd91
Step 6/22 : COPY ./build.sbt ./build.sbt
---> Using cache
---> d30058c451fc
Step 7/22 : COPY ./project/build.properties ./project/build.properties
---> Using cache
---> 7451eb63303f
Step 8/22 : COPY ./project/plugins.sbt ./project/plugins.sbt
---> Using cache
---> 79ac2d1e5ff5
Step 9/22 : RUN ./sbt -sbt-dir ./sbt-dir -ivy ./ivy update
---> Running in 609104e7045e
Getting org.scala-sbt sbt 1.0.3 ...
任何人都可以解释为什么Docker没有在这里使用缓存吗? 解释缓存如何确定何时使用缓存的解释链接也是可以的。据我所知,Docker应该使用缓存,直到RUN命令的签名发生变化。
先谢谢
答案 0 :(得分:3)
我顺便找到了答案:) Dockerfile本身还可以,但是我可以通过docker history
找到一个问题,该问题显示了由docker执行的真实shell命令。
问题在于,ARG BUILD_VERSION
导致docker向每个运行命令添加了/bin/sh -c "ARG=123 ./sbt ..."
这样的环境变量。每当arg更改时,这将导致不同的调用签名和不同的哈希,因此不会从缓存中应用run命令。要解决此问题,只需将ARG
移至需要它的第一个RUN
命令。
FROM openjdk:8 as workspace
WORKDIR /build
COPY ./sbt ./sbt
COPY ./sbt-dist ./sbt-dist
COPY ./build.sbt ./build.sbt
COPY ./project/build.properties ./project/build.properties
COPY ./project/plugins.sbt ./project/plugins.sbt
RUN ./sbt -sbt-dir ./sbt-dir -ivy ./ivy update
COPY ./ ./
# Embedded postgres need to be run as non-root user
RUN useradd -ms /bin/bash runner
RUN chown -R runner /build
USER runner
RUN ./sbt -sbt-dir ./sbt-dir -ivy ./ivy clean test
ARG BUILD_VERSION
RUN ./sbt -sbt-dir ./sbt-dir -ivy ./ivy docker:stage -Ddocker.image.version="${BUILD_VERSION}"
答案 1 :(得分:0)
当docker build输出显示时,建筑物在阶段停止使用缓存:
4:32:35 PMStep 4/22 : ADD ./sbt ./sbt
4:32:36 PM---> 7a9e21819cea
这种情况正在发生,因为主机上的./sbt
文件夹已发生更改,因此docker将重新运行ADD
指令。从那时起,docker将不再使用缓存,因为基础层无效,导致其后的图层也无效。
更改可能在目录的内容中,而是一些微不足道的内容,例如时间戳。
作为最佳实践,要获得构建缓存机制的优势,您应该将经常更改的指令延迟到Dockerfile的底部。通常,将源添加到docker镜像是这些步骤之一,它们会在构建之间进行频繁更改。