Using Docker Cache Layer to Speed Up Build Time
Tags: webdev, aws, devops, docker
Published: 2023-12-22 00:00:00

I came across a [video](https://www.youtube.com/watch?v=8vXoMqWgbQQ) about tips and tricks for Docker. In this video, the she gives us tips on how to utilize Docker cache layers. The main point is that Docker images have multiple layers, and each layer is cached by Docker. When there is a change in one layer, the layer below it will be invalidated.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u1089e0kqs5wishzgdfh.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iqusc7cu9u6pspohmisf.png)

Now, let’s examine our production Docker file. We can see that the layer is not optimized because we copy our code and then install the package. This can slow down the build process because if we change one file on our server app.

```jsx
FROM node:18-alpine as builder

WORKDIR /main

COPY packages/libs packages/libs
COPY packages/validation packages/validation
COPY apps/server apps/server

COPY package.json .
COPY yarn.lock .

RUN yarn install --pure-lockfile --cache-folder ./yarncache; rm -rf ./yarncache;
RUN yarn workspace server build
RUN yarn install --production --pure-lockfile --cache-folder ./yarncacheprod; rm -rf ./yarncacheprod;

FROM node:18-alpine as runner

WORKDIR /main
COPY --from=builder /main/packages ./packages
COPY --from=builder /main/apps ./apps
COPY --from=builder /main/node_modules ./node_modules
COPY --from=builder /main/package.json ./

```

Now, let’s try to test it; first, let’s add some changes to our file.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0nh34gyfs3k08fx7aph4.png)

Then let’s build the Docker file.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6ns6dk2loazmq11gp34q.png)

We can see the build time is more or less 32 seconds. Now let’s add more changes and see whether the build is actually cached or not.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o66jwbil02n8h8i8l5c0.png)

Then let’s build the Docker file one more time.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6tpktrwadoe9ig91wrwh.png)

Now let’s build the Docker file for the last time without change anything and see if the duration will be similar or not.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s1i431o1px3237w4u7pr.png)

As we can see, when Docker utilizes its cache, the build time goes down to 2 seconds. So, we have already proven that changing the file content will invalidate the cache.

## **Optimizing the Layer Cache**

To optimize our Dockerfile, we should consider which layer frequently changes and which layer takes longer to build. Then, we rearrange those layers to make sure that the frequently changed layer is placed at the bottom of the Dockerfile.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bt9g3zk9yqcp7q8tbs31.png)

Now let’s see the Dockerfile after we optimized it.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u3yqkli6n2dasvbfokha.png)



The main change that we made is to copy the **`package.json`** file, then we do the installation process after that. Although we do installation again after the build process, this installation will be faster because it only removes the files that are not for production mode.

## **Performance Test after Optimization**

First, let’s create some changes in our file.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x5yij8h1yyd5osa28g0l.png)

Then, let’s try to build the Dockerfile.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hocpxpdp8frlnjk10wnp.png)

Then, let’s create another change.



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f27v5a9itsp2rqpba9kw.png)





Lastly, let’s build the Dockerfile again.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/quma2ls88wnz4tkmp4tf.png)



As we can see, after we changed the Dockerfile, the build time went down from 30 seconds to 11 seconds every time we built the image. One caveat for this method: if we have changes in **`package.json`**, then Docker needs to invalidate all the layers after that. You can see the code for this part [here](https://github.com/akbarnafisa/aws-devops-fullstack/tree/7-improve-docker-build-time)