Hello to all the readers!
Docker image is built in layers. Each instruction that is written in Dockerfile translates into an image layer by the builder.
When the image is re-built, builder will re-use layers from earlier builds. If any layer is unchanged, then that layer is picked up from the build cache.
However, if a layer has changed since last build, then that layer and all layers that follow it are also rebuilt.
Let us consider an example:
FROM golang:1.20-alpine
WORKDIR /src
COPY . .
RUN go mod download
RUN go build -o /bin/client ./cmd/client
RUN go build -o /bin/server ./cmd/server
ENTRYPOINT [ "/bin/server" ]
In this Dockerfile, the project repository is copied and then go modules are downloaded. If any file in project changes, then COPY layer will change and thereby go modules will be downloaded again. Although no module has changed but still it spends time downloading them.
Therefore, we should change above Dockerfile instructions to a better form.
FROM golang:1.20-alpine
WORKDIR /src
COPY go.mod go.sum .
RUN go mod download
COPY . .
RUN go build -o /bin/client ./cmd/client
RUN go build -o /bin/server ./cmd/server
ENTRYPOINT [ "/bin/server" ]
This time, we have copied go.mod and go.sum that track project dependencies. And then downloaded go modules and then copied project repository inside container.
Now if a file is changed in the repo, go modules won’t be downloaded again and that layer will be reused. This saves build time.