TL;DR
This post provides hands-on tutorial on how to use a private RUN cache that is defined by RUN –mount=type=cache, sharing=private in Dockerfile. Here is a snippet of Dockerfile.
RUN --mount=type=cache,id=private-cache,target=/root/.cache,sharing=private \
echo $(date):" private1 is writing..." && \
echo $(date)": Hello from private1" >> /root/.cache/private.log && \
sleep 10 && \
echo "--- private.log ---------" && \
cat /root/.cache/private.log && \
echo "------------------------" && \
echo $(date):" private1 finish writing"

RUN cache has three sharing types (shared, private and locked) . In the two previous posts, I explained shared and locked types’ behaviors. In this post, we will try to use a private type.
Clone the repository from GitHub
I already prepared contents for hands-on, so please clone it from my repository named buildkit–101.
git clone https://github.com/yukinakanaka/buildkit-101.git
Then, move to the following directory.
cd buildkit-101/run-cache/private
Create a private RUN cache

Dockerfile.private1 contains RUN –mount=type=cache,id=private-cache,target=/root/.cache,sharing=private. It will create a RUN cache during building a DockerImage.
cat Dockerfile.private1
FROM debian:12.4-slim
RUN mkdir -p /root/.cache
COPY rebuild-trigger .
RUN date
RUN --mount=type=cache,id=private-cache,target=/root/.cache,sharing=private \
echo $(date):" private1 is writing..." && \
echo $(date)": Hello from private1" >> /root/.cache/private.log && \
sleep 10 && \
echo "--- private.log ---------" && \
cat /root/.cache/private.log && \
echo "------------------------" && \
echo $(date):" private1 finish writing"
RUN date
Let’s build a DockerImage from Dockerfile.private1!
docker build --progress=plain -f Dockerfile.private1 .
In the build log, you can see that the build process wrote a log in /root/.cache/private.log. The file private.log was stored in a cache named private-cache!
#9 [stage-0 5/6] RUN --mount=type=cache,id=private-cache,target=/root/.cache,sharing=private echo $(date):" private1 is writing..." && echo $(date)": Hello from private1" >> /root/.cache/private.log && sleep 10 && echo "--- private.log ---------" && cat /root/.cache/private.log && echo "------------------------" && echo $(date):" private1 finish writing"
#9 0.077 Sun Mar 10 05:49:38 UTC 2024: private1 is writing...
#9 10.08 --- private.log ---------
#9 10.08 Sun Mar 10 05:49:38 UTC 2024: Hello from private1
#9 10.08 ------------------------
#9 10.08 Sun Mar 10 05:49:48 UTC 2024: private1 finish writing
#9 DONE 10.1s
The private cache behavior
Multiple writers
Multiple processes cannot write the same private cache at same time. When there are multiple writers, the new private cache will be created.

Let’s check the private cache behavior by running two build processes at the same time!
echo $RANDOM > rebuild-trigger
docker build --progress=plain -f Dockerfile.private1 . 1>private1.log 2>&1 &
sleep 1
docker build --progress=plain -f Dockerfile.private2 . 1>private2.log 2>&1 &
Please check the logs in private2.log. You can see only private2’s log, you cannot see the private1’s log that was written in previous step. This means that a new cache was created!
$ cat private2.log
...
#9 10.09 --- private.log ---------
#9 10.09 Sun Mar 10 05:50:09 UTC 2024: Hello from private2
#9 10.09 ------------------------
...
Please check the logs in private1.log, too. You can see private1 uses the same cache in the previous step.
$ cat private1.log
...
#9 10.28 --- private.log ---------
#9 10.28 Sun Mar 10 05:49:38 UTC 2024: Hello from private1
#9 10.28 Sun Mar 10 05:50:09 UTC 2024: Hello from private1
#9 10.28 ------------------------
...
The first cache was deleted?
We found the new cache was created. Then, what about the first created cache? Let’s check it.
echo $RANDOM > rebuild-trigger
docker build --progress=plain -f Dockerfile.private1 . 1>private1.log 2>&1 &
sleep 1
docker build --progress=plain -f Dockerfile.private2 . 1>private2.log 2>&1 &

You can find the first private.log in private1.log or private2.log. In my case, I found it in private1.log. This means the old cache is not deleted!
$ cat private1.log
...
#9 10.26 --- private.log ---------
#9 10.26 Sun Mar 10 05:49:38 UTC 2024: Hello from private1
#9 10.26 Sun Mar 10 05:50:09 UTC 2024: Hello from private1
#9 10.26 Sun Mar 10 05:50:48 UTC 2024: Hello from private1
#9 10.26 ------------------------
...
Appendix: Which cache is used in a next build?
I tried to find a rule for which cache is used preferentially, but I was not able to find it. Sometimes, the old cache is used, and sometime the new cache was used. Also, its priority sometimes was changed after multiple writers ran.
Wrap up
In this post, I explained the behavior private-type RUN cache between builds. These are features of private-type RUN cache. 🐳
- A new cache is created when some build process is using existing cache.
- The first (old) cache is not deleted.
Please check bellow if you’re interested in other type of cache.
- shared-type:Use a RUN cache between builds in BuildKit
- locked-type: Use a locked RUN cache between builds in BuildKit

