如何强制执行 Docker 镜像的干净构建?
当您执行 Docker pull 命令或 Docker run 命令时,守护进程首先通过比较镜像的摘要来检查本地机器中是否存在类似的镜像。
如果找到匹配项,则无需搜索注册表以查找镜像,守护进程只需创建已存在镜像的副本即可。但是,如果找不到副本,它将开始从注册表中提取它。当您尝试使用 Dockerfile 构建镜像时,情况也是如此。
我们都知道 Docker 镜像是多层文件,包含多个彼此叠加的镜像层。Dockerfile 中提到的每个指令都负责创建一个新层。
一个层仅包含前一层和当前层之间的差异。如果您之前构建过相同的镜像,守护进程将查找包含相同镜像层的缓存。如果找到后续缓存,它将简单地使用此缓存,而不是构建新层。
但是,在某些情况下,您可能希望强制执行镜像的干净构建,即使后续层的构建缓存存在。在这里,Docker 也能帮到您。让我们看看如何强制干净构建 Docker 镜像。
考虑以下 Dockerfile。
RUN apt-get update RUN apt-get -y install vim
在上面的 Dockerfile 中,我们在单独的行中使用了两个不同的 RUN 指令。这会导致构建单独的镜像层和构建缓存。当 Docker 守护进程处理更新命令(例如 RUN apt-get -y update)时,不会比较容器中更新命令作用的那些包以确定是否发生了缓存命中。在这种情况下,仅比较命令字符串以查找匹配项。
与其对两个连续的 RUN 指令使用两行,不如将它们链接起来以减少镜像层的数量,从而减少缓存命中的可能性。
RUN apt-get update && apt-get -y install vim
如果您根本不想允许守护进程执行缓存检查,可以使用 **--no-cache** 选项来实现。当您使用 Docker build 命令构建 Docker 镜像时,您可以简单地使用 --no-cache 选项,这将允许您指示守护进程不要查找已存在的镜像层,而只是强制干净构建镜像。
例如,如果您想从以下 Dockerfile 构建镜像 -
FROM ubuntu:latest WORKDIR /app COPY . . MAINTAINER [email protected] RUN apt-get -y update RUN apt-get install -y openjdk-7-jdk RUN apt-get install -y git-core RUN apt-get install -y build-essential RUN apt-get install -y lsb-release CMD ["javac", "sample.java"]
假设您之前已经构建过此镜像,并且现在您在构建上下文中进行了一些更改。因此,COPY 指令缓存以及所有后续指令的缓存都会失效。如果您没有进行任何更改并且再次构建了镜像,则不会发生缓存失效,守护进程只需使用镜像层的现有缓存来构建镜像。
这是默认行为,如果您想覆盖此默认行为,可以在 Docker build 命令中使用 --no-cache 选项。
$ docker build --no-cache -t sample-image:sample-tag .
当您执行此命令时,守护进程不会查找现有镜像层的缓存构建,而是会强制从 Dockerfile 中干净构建 Docker 镜像。
如果您使用 Docker compose,可以使用以下命令。
$ docker-compose build --no-cache
您还可以将其与 up 命令链接以重新创建所有容器。
$ docker-compose build --no-cache && docker-compose up -d --force-recreate
请注意,这些方法不使用缓存,但构建器和基础镜像是使用 FROM 指令引用的。您可以使用以下方法清理构建器缓存 -
$ docker builder prune -af
如果您不想使用其缓存,也可以清除父镜像。
$ docker image rm -f parent-image
这些是您可以采用以强制干净构建镜像并避免使用镜像层缓存的最常见方法。最好且可能最简单的选择是使用 --no-cache 选项。