Use a RUN cache between builds in BuildKit

TL;DR

This post provides hands-on tutorial on how to use RUN cache that is defined by RUN –mount=type=cache,sharing=shared in Dockerfile. Here is a snippet of Dockerfile.

RUN --mount=type=cache,id=shared-cache,target=/root/.cache,sharing=shared \
  echo $(date)": Hello from shared1" >> /root/.cache/shared.log && \
  cat /root/.cache/shared.log
Sharing cache between builds

There are several kinds of cache in docker build, such as the layer cache, the build result cache. In this post, I will explain a cache that is defined by RUN –mount=type=cache in Dockerfile. I will call it RUN cache explicitly to distinguish it from other caches.

RUN cache has three sharing types (shared, private and locked) . The shared type is a default type and I will use it in this post. A shared cache mount can be used concurrently by multiple writers.

  1. Clone the repository from GitHub
  2. Create a RUN cache
  3. Use and Update the RUN cache from a different build
  4. Use and Update the RUN cache from a different build with a different Dockerfile
  5. Wrap up

Clone the repository from GitHub

I already prepared contents for hands-on, so please clone it from my repository named buildkit101.

git clone https://github.com/yukinakanaka/buildkit-101.git

Then, move to the following directory.

cd buildkit-101/run-cache/shared 

Create a RUN cache

Create a RUN cache

Dockerfile.shared1 contains RUN –mount=type=cache,id=shared-cache,target=/root/.cache,sharing=shared. It will create a RUN cache during building a DockerImage.

$ cat Dockerfile.shared1
FROM debian:12.4-slim
RUN mkdir -p /root/.cache
COPY rebuild-trigger .

RUN date
RUN --mount=type=cache,id=shared-cache,target=/root/.cache,sharing=shared \
  echo $(date)": Hello from shared1" >> /root/.cache/shared.log && \
  cat /root/.cache/shared.log
RUN date%     

Let’s build a DockerImage from Dockerfile.shared1!

docker build --progress=plain -f Dockerfile.shared1 .

In the build log, you can see that the build process wrote a log in /root/.cache/shared.log. The file shared.log was stored in a cache named shared-cache!

#9 [stage-0 5/6] RUN --mount=type=cache,id=shared-cache,target=/root/.cache,sharing=shared   echo $(date)": Hello from shared1" >> /root/.cache/shared.log &&   cat /root/.cache/shared.log

#9 0.290 Sun Feb 4 04:30:27 UTC 2024: Hello from shared1. <<<< Content of shared.log

#9 DONE 0.3s

Use and Update the RUN cache from a different build

Use and Update the RUN cache from a different build

Let’s try to use shared.log in a different build with the same Dockerfile! Before build, we need to change some files so that the builder rebuild a image without the layer cache.

Change a file named rebuild-trigger by the following command.

echo $RANDOM > rebuild-trigger

Build a DockerImage from Dockerfile.shared1 again!

docker build --progress=plain -f Dockerfile.shared1 .

If you can see that shared.log has a new line, you successfully used and updated the RUN cache!

#9 [stage-0 5/6] RUN --mount=type=cache,id=shared-cache,target=/root/.cache,sharing=shared   echo $(date)": Hello from shared1" >> /root/.cache/shared.log &&   cat /root/.cache/shared.log

#9 0.299 Sun Feb 4 04:30:27 UTC 2024: Hello from shared1
#9 0.299 Sun Feb 4 04:48:45 UTC 2024: Hello from shared1 <<<< New line

#9 DONE 0.3s

Use and Update the RUN cache from a different build with a different Dockerfile

Use and Update the RUN cache with a different Dockerfile

Run cache can be used from from a different build with a different Dockerfile when Dockerfiles use a same id’s RUN cache.

Please check if Dockerfile.shared1 and Dockerfile.shared2 uses the same id’s RUN cache. The id is shared-cache.

$ grep "id=" -R .
./Dockerfile.shared1:RUN --mount=type=cache,id=shared-cache,target=/root/.cache,sharing=shared \
./Dockerfile.shared2:RUN --mount=type=cache,id=shared-cache,target=/root/.cache,sharing=shared \

Build a DockerImage from Dockerfile.shared2!

docker build --progress=plain -f Dockerfile.shared2 .

If you can see that shared.log has a new line, you successfully used and updated the cache!

#9 [stage-0 5/6] RUN --mount=type=cache,id=shared-cache,target=/root/.cache,sharing=shared   echo $(date)": Hello from shared2" >> /root/.cache/shared.log &&   cat /root/.cache/shared.log

#9 0.106 Sun Feb 4 04:30:27 UTC 2024: Hello from shared1
#9 0.106 Sun Feb 4 04:48:45 UTC 2024: Hello from shared1
#9 0.106 Sun Feb 4 05:26:09 UTC 2024: Hello from shared2 <<<< New line

#9 DONE 0.1s

Wrap up

In this post, I explained how to use the shared-type RUN cache between builds.🐳

Please check bellow if you’re interested in other type of cache.