Join our Discord Server
Ajeet Raina Ajeet Singh Raina is a former Docker Captain, Community Leader and Distinguished Arm Ambassador. He is a founder of Collabnix blogging site and has authored more than 700+ blogs on Docker, Kubernetes and Cloud-Native Technology. He runs a community Slack of 9800+ members and discord server close to 2600+ members. You can follow him on Twitter(@ajeetsraina).

Understanding Docker Build Cache

2 min read

Docker provides a powerful and efficient way to package and distribute applications using containers. One key aspect of optimizing the Docker image-building process is understanding how Docker caching works. In this blog post, we’ll explore the caching mechanism in Docker and how it impacts the speed and efficiency of your image builds.

The Basics of Docker Caching

When you first build a Dockerfile, Docker caches the results so that subsequent builds become fast. When a RUN, ADD, COPY or a similar instruction is encountered, a new layer is created over the base image. The file structure formed is stored by default at /var/lib/docker in a Linux based host system. All base images and containers are stored in this folder only.

These files/directories are stored on disk and disk operations are time-consuming and resource-intensive. If these files/filesystem objects remain unchanged during future builds or during container creations, Docker cache becomes useful to save time. New containers or images are created at a faster rate since disk operations are eliminated.

When you build a Docker image, Docker uses a caching mechanism to avoid redundant work and speed up the process. The caching strategy differs for the ADD/COPY commands and the RUN commands.

1. ADD/COPY Commands:

When you use ADD or COPY commands to copy files into the container image, Docker calculates a checksum for the files. This checksum acts as a unique identifier for the set of files. If the same files are used in subsequent builds and the checksum matches, Docker can reuse the cache. However, any change to a file, such as modifications to contents, filenames, or permissions, results in a new checksum. This change invalidates the cache, and Docker will rebuild subsequent layers.

2. RUN Commands:

For RUN commands, Docker caches the command itself. If the same RUN command is used in multiple builds, Docker can reuse the cache. However, even if the outcome of the command is the same, any change to the command itself will invalidate the cache. This means that modifying the command, even if it produces the same result, will trigger a rebuild of subsequent layers.

Example: Illustrating Docker Caching in Action

Let’s walk through a simple example to see how Docker caching behaves in practice. Consider the following Dockerfile:

# Dockerfile

# Step 1: Copy files into the image
COPY ./app /app

# Step 2: Install dependencies using a RUN command
RUN pip install -r /app/requirements.txt

# Step 3: Set the working directory
WORKDIR /app

# Step 4: Start the application
CMD ["python", "app.py"]

Scenario 1: No Changes

In the first build, we copy files, install dependencies, and set the working directory:

docker build -t myapp:1.0 .

If we make no changes to the files or the RUN command and build again:

docker build -t myapp:1.1 .

Docker recognizes that nothing has changed, and it efficiently reuses the cache, resulting in a faster build.

Scenario 2: Changes Made

Now, let’s make a change to app.py:

# Modify app.py
echo "print('Hello, Docker!')" > /app/app.py

# Build the image
docker build -t myapp:2.0 .

Since we modified app.py, the checksum changes, invalidating the cache. Subsequent layers, including the RUN command, will be rebuilt.

# Build again with no changes
docker build -t myapp:2.1 .

Even though no changes were made to the files this time, the cache from the previous modification is still invalidated, leading to a rebuild of subsequent layers.

Using –no-cache

Let’s see what happens when we rebuild an image which was already built.

Dockerfile used in this case is as such:

Dockerfile

We first built this Dockerfile to create testimage:latest. Now, building testimage:v2.

Cache

As you can see in the image, every instruction was executed using the cache as the same file was already built before.

Usually, caching is desirable and beneficial, but at times we want new rebuilds due to changes in layers which could not be detected by the docker daemon. For example, change of command provided with RUN instruction. Sometimes, due to faulty installations, our application crashes. We wish to install everything from the beginning, but the cache may create conflicts.

To resolve such issues, we can opt for builds using –no-cache flag. With this flag, cache is ignored and the build is treated as a new one and everything begins from the start.

Let’s build the same Dockerfile again. This time we will use the option –no-cache.

No Cache

As you can see, the build is fresh and no cache is used.

Conclusion

Understanding Docker caching is crucial for optimizing your Docker image builds. By being aware of how changes in files and commands impact the caching mechanism, you can make informed decisions to speed up your development workflow and ensure efficient use of resources.

Remember that Docker caching is a powerful tool, but it requires careful consideration to avoid unexpected behaviors. By striking the right balance between caching and rebuilding when necessary, you can create Docker images that are not only efficient but also consistent and reliable across different environments.

Have Queries? Join https://launchpass.com/collabnix

Ajeet Raina Ajeet Singh Raina is a former Docker Captain, Community Leader and Distinguished Arm Ambassador. He is a founder of Collabnix blogging site and has authored more than 700+ blogs on Docker, Kubernetes and Cloud-Native Technology. He runs a community Slack of 9800+ members and discord server close to 2600+ members. You can follow him on Twitter(@ajeetsraina).
Join our Discord Server
Index