Docker镜像的分层结构
Docker镜像是由一层一层的文件系统组成,UnionFS将这些镜像层堆叠在一起
镜像层是只读的,构建完成后就不能更改了,即使在新的镜像层修改或删除了某些文件,也不会影响之前的镜像层内容
用Dockerfile构建镜像时,每个指令都会创建一个新的镜像层,镜像层会被缓存和复用
构建缓存的基本规则
构建镜像时,Docker 按照顺序逐步执行 Dockerfile 中的指令。对于每条指令,Docker 检查它是否可以重用构建缓存中的指令。
如果引用的父镜像在构建缓存中,下一个指令将会和所有从该基础镜像派生的子镜像做比较,如果和其中一个子镜像的指令相同,那么缓存命中,否则缓存失效
在大部分情况下,通过比较Dockerfile中的指令和子镜像已经足够了,但是有些指令需要进一步的检查
对于ADD和COPY指令,文件的内容会被检查,并且会计算每一个文件的校验码。在缓存查找期间,如果文件内容或元数据发生更改,那么缓存就会失效
除了ADD和COPY指令之外,缓存检查不会查看容器中的文件来判断是否命中缓存。例如,在处理RUN apt-get -y update指令时,不会检查容器中的更新文件来确定是否命中缓存,这种情况下只会检查指定字符串是否相同
一旦缓存失效,所有后续的 Dockerfile 指令都会生成新的镜像层,不再使用缓存。
通常的最佳实践是确保那些不经常变化的步骤放在Dockerfile的前面,以便最大限度地利用缓存。
如何充分利用缓存
将多个命令合并成单个RUN指令时,同时也要考虑将变更频率不同的命令分开
指令从变更不频繁到变更频繁的顺序来写
a. 一般源代码会经常变化,所以要把安装依赖等不经常变动的步骤写在前面,拷贝源代码等经常变动的步骤写在后面
b.如果是Python项目的话,先拷贝requerements.txt,然后进行pip install requerements.txt,最后再进行COPY代码
ARG指令的变量值变化会导致缓存失效,所以最好在使用前定义,不要过早使用
来源:https://blog.csdn.net/xingjingb/article/details/135321030
不使用缓存:docker build --no-cache -t myimage .
多阶段构建也可以用缓存,主要用于减少镜像的体积。
|
|
# 第一阶段:编译 Go 代码 FROM golang:1.16 AS builder WORKDIR /app COPY go.mod go.sum ./ RUN go mod download COPY . . RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o myapp . # 第二阶段:构建生产镜像 FROM alpine:latest RUN apk --no-cache add ca-certificates WORKDIR /root/ COPY --from=builder /app/myapp . EXPOSE 8080 CMD ["./myapp"] |
「三年博客,如果觉得我的文章对您有用,请帮助本站成长」
共有 0 - dockerfile 缓存机制和分阶段构建