Docker image builds can utilize cached image layers to improve build speeds. However, sometimes a full, clean rebuild of the Docker image is required. This article covers how to perform a clean Docker image build without leveraging any cached image layers using the "--no-cache
" flag.
Background on Docker Image Building
When running docker build
, Docker checks for existing intermediate image layers it can reuse to optimize the build process. By default, if files in the Docker context change from previous builds, Docker will rebuild those layers, but reuse other cached layers to speed up builds.
For example, consider this Dockerfile:
FROM ubuntu:latest
RUN apt-get update
RUN apt-get install -y nginx
COPY index.html /var/www/html
The first time this Dockerfile is built, Docker will:
- Pull the
ubuntu:latest
base image - Run
apt-get update
and commit that layer - Install nginx and commit that layer
- Copy over index.html and commit that layer
On the next build, if only index.html
changed, Docker would:
- Reuse existing
ubuntu:latest
layer from cache - Reuse apt update layer from cache
- Reuse nginx install layer from cache
- Only rebuild the final layer copying
index.html
By leveraging its layer cache intelligently like this, Docker can avoid unnecessary work and speed up builds.
However, sometimes you need to force Docker to rebuild the full image from scratch using --no-cache
.
When to Use docker build --no-cache
There are a few common reasons you may want to utilize --no-cache
for clean Docker builds:
-
Base image was updated: If your
FROM
base image was updated to a new version, you likely want to rebuild fully from latest base image version. -
Dependency changes: If Dockerfile depends on files not copied into image that could have changed like package manager lock files or host mounted volumes, may need full rebuild.
-
Build consistency: Sometimes you want 100% clean/consistent builds, avoiding any potential issues with cache inconsistencies.
-
Security policies: In some corporate environments, security policies may require clean full rebuilds of images to avoid risks from relying on cache layers between builds.
Using --no-cache
forces Docker to rebuild the full image in isolation without relying on any cached image layers from previous builds.
How docker build --no-cache
Works
When Docker builds an image, it checks if it has existing images layers from previous builds it can reuse before executing each image layer step defined in the Dockerfile.
The --no-cache=true
flag tells Docker to ignore any cached image layers and build each layer from scratch instead.
For example, consider this Dockerfile:
# Build stage
FROM golang AS build
...
# Final stage
FROM alpine
COPY --from=build /app /app
Normally on rebuilds Docker would reuse the golang
and alpine
base images from cache.
With --no-cache
Docker will pull the latest versions of golang
and alpine
images ignoring cache, fully recreating the build, before copying artifacts over into the final image.
Using docker build --no-cache
To perform a Docker build without layer cache, simply add the --no-cache=true
flag to your docker build
command:
docker build --no-cache=true -t myimage .
You can also use the shorter -no-cache
format:
docker build -no-cache -t myimage .
That‘s all it takes to force a clean Docker image build!
Let‘s walk through an example to see this in practice.
Dockerfile Example
First, consider this simple Dockerfile that builds a Nginx web server:
# Base off latest ubuntu LTS
FROM ubuntu:jammy
# Metadata
LABEL maintainer="sven@example.com"
# Update packages
RUN apt-get update && apt-get install -y \
nginx
# Configure nginx
COPY nginx.conf /etc/nginx/
# Copy site data
COPY html /var/www/html
# Open port 80
EXPOSE 80
# Start Nginx
CMD ["nginx", "-g", "daemon off;"]
Next, build the initial Docker image:
$ docker build -t my-site:v1 .
[+] Building 8.2s (16/16) FINISHED
=> [internal] load build definition from Dockerfile 0.1s
=> => resolving docker.io/library/ubuntu:jammy 0.1s
=> [auth] library/ubuntu:pull token for registry-1.docker.io 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 35B 0.0s
=> [internal] load metadata for docker.io/library/ubuntu:jammy 1.7s
=> [ 1/11] FROM docker.io/library/ubuntu:jammy@sha256:416d97810e5cc1ed2739aaeaf1e2c4c7debd16f58aff157 0.0s
=> CACHED [ 2/11] RUN apt-get update && apt-get install -y nginx 0.0s
=> CACHED [ 3/11] COPY nginx.conf /etc/nginx/ 0.0s
=> CACHED [ 4/11] COPY html /var/www/html 0.0s
=> CACHED [ 5/11] EXPOSE 80 0.0s
=> CACHED [ 6/11] CMD ["nginx" "-g" "daemon off;"] 0.0s
=> exporting to image 1.4s
=> => exporting layers 1.4s
=> => writing image sha256:8ad0d5cee6b7fed919561e9c52256595c9535f25862f3c69dab848c368fcd329 0.0s
=> => naming to docker.io/library/my-site:v1
We can test it out with:
$ docker run -dp 80:80 my-site:v1
And we‘ll see our site running at http://localhost.
Now let‘s make some changes and rebuild.
Rebuilding Without --no-cache
First, edit html/index.html
locally and update some text.
Next, rebuild with docker build
:
$ docker build -t my-site:v2 .
[+] Building 1.8s (9/9) FINISHED
=> [internal] load build definition from Dockerfile 0.1s
=> => transferring dockerfile: 37B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 35B 0.0s
=> [internal] load metadata for docker.io/library/ubuntu:jammy 1.7s
=> [ 1/6] FROM docker.io/library/ubuntu:jammy@sha256:416d97810e5cc1ed2739aaeaf1e2c4c7debd16f58aff157a3d0c5d 0.0s
=> CACHED [ 2/6] RUN apt-get update && apt-get install -y nginx 0.0s
=> CACHED [ 3/6] COPY nginx.conf /etc/nginx/ 0.0s
=> CACHED [ 4/6] EXPOSE 80 0.0s
=> CACHED [ 5/6] CMD ["nginx" "-g" "daemon off;"] 0.0s
=> [ 6/6] COPY html /var/www/html 0.7s
=> exporting to image 0.1s
=> => exporting layers 0.1s
=> => writing image sha256:5e17f3d3200e9dff63af92adaa43c989e2339e225d0a9b2d984e19d9233bc9ce 0.0s
=> => naming to docker.io/library/my-site:v2
Note how Docker reused existing cache image layers for the initial Dockerfile instructions, only rebuilding the final layer copying our updated html
.
This leverages cache to optimize build performance, but doesn‘t give us a fully clean build.
Rebuilding with --no-cache
Now, let‘s rebuild using --no-cache
for a full, clean build:
$ docker build --no-cache -t my-site:v3 .
[+] Building 2m0s (16/16) FINISHED
=> [internal] load build definition from Dockerfile 0.1s
=> => transferring dockerfile: 37B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 35B 0.0s
=> [internal] load metadata for docker.io/library/ubuntu:jammy 1.6s
=> [auth] library/ubuntu:pull token for registry-1.docker.io 0.0s
=> [ 1/11] FROM docker.io/library/ubuntu:jammy@sha256:416d97810e5cc1ed2739aaeaf1e2c4c7debd16f58aff157a3d0c5d 0.0s
=> [internal] load build context 0.1s
=> => transferring context: 5.49kB 0.1s
=> CACHED [ 2/11] RUN apt-get update && apt-get install -y nginx 0.0s
=> CACHED [ 3/11] COPY nginx.conf /etc/nginx/ 0.0s
=> CACHED [ 4/11] EXPOSE 80 0.0s
=> CACHED [ 5/11] CMD ["nginx" "-g" "daemon off;"] 0.0s
=> [ 6/11] COPY html /var/www/html 1.3s
=> exporting to image 0.2s
=> => exporting layers 0.2s
=> => writing image sha256:41262d86610e8331bfbab672bc0310d7bd0aca5258c7f9c6deafa4c603249eb9 0.0s
=> => naming to docker.io/library/my-site:v3
Now on rebuild, Docker did not leverage any cache image layers from prior builds.
It pulled a brand new ubuntu base image, and rebuilt the full Docker image from scratch.
So using --no-cache
gave us a fully clean, consistent Docker image build after we updated our source code.
This can be useful in many situations when you need 100% clean Docker builds.
Caching Specific Build Stages
When using multi-stage Docker builds, you can also selectively control layer caching.
For example:
# Build stage
FROM maven AS build
COPY . /src
RUN mvn package -f /src
# Package stage
FROM tomcat
COPY --from=build /src/target/app.war /webapps
To force a clean rebuild of just the build stage, do:
docker build --no-cache=true --target build -t app .
This will recreate the maven
builder stage from scratch, while still utilizing cache for the packaging stage.
So with multi-stage builds, you have granular control over layer caching per stage.
Other Cache Configuration Options
In addition to --no-cache
, Docker also offers some other cache tuning options:
--cache-from
– Prefetch images for cache sources--no-cache=false
– Only rebuild changed layers, but use cache (default behavior)--pull
– Always attempt to pull newer base images--cache-to
– Save resulting image for future cache source
For example, to use a specific cached image as the cache source:
docker build --cache-from myimage:cachebase -t mybuild .
This leverages advanced cached images for more repeatable builds.
So while --no-cache
disables all caching, you can also fine-tune cache behavior if needed.
Conclusion
While Docker caching often improves image build speeds, utilizing --no-cache
forces clean full rebuilds.
Key reasons to disable Docker cache with --no-cache
:
- Base images updated
- Dependency changes
- Consistent/clean builds needed
- Corporate security requirements
Simply add --no-cache
or -no-cache
to your docker build
and Docker will rebuild the full image from scratch.
This guide covered common use cases, implementation, and examples using --no-cache
for clean cached Docker image building.
Disabling caching provides complete control over the integrity and consistency of your Docker images.