In Docker, when packages are installed via a package manager, an index is cached locally by default. This index should either be cleaned up or stored in a dedicated cache mount.

Why is this an issue?

Docker images should only contain the necessary data. The package index is redundant for the correct operation of the installed software. Storing an index also increases the size of the Docker image. It should be reduced to speed up deployments and reduce storage and bandwidth.

Exceptions

In multi-stage builds, the rule only scans instructions that are part of the final image.

How to fix it

Code examples

Noncompliant code example

For apk:

RUN apk add nginx

For apt-get:

RUN apt-get update \
  && apt-get install nginx

For aptitude:

RUN aptitude update \
  && aptitude install nginx

For apt:

RUN apt update \
  && apt install nginx

For apt-get, without a cache mount:

RUN apt-get update \
  && apt-get install nginx

Compliant solution

For apk:

RUN apk --no-cache add nginx

RUN apk add nginx \
  && apk cache clean

RUN apk add nginx \
  && rm -rf /var/cache/apk/*

# This cache location is only used in specific distributions / configurations
RUN apk add nginx \
  && rm -rf /etc/apk/cache/*

For apt-get:

RUN apt-get update \
  && apt-get install nginx \
  && apt-get clean

RUN apt-get update \
  && apt-get install nginx \
  && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*

For aptitude:

RUN aptitude update \
  && aptitude install nginx \
  && aptitude clean

RUN aptitude update \
  && aptitude install nginx \
  && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*

For apt:

RUN apt update \
  && apt install nginx \
  && apt clean

RUN apt update \
  && apt install nginx \
  && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*

For apt-get, with a cache mount:

RUN \
  --mount=type=cache,target=/var/cache/apt,sharing=locked \
  --mount=type=cache,target=/var/lib/apt,sharing=locked \
  apt-get update \
  && apt-get install nginx

How does this work?

When installing packages using apt-get, aptitude or apt these package managers store an index in the Docker image layer in /var/lib/apt/lists. Using apk, it will store an index in /var/cache/apk/. In some distributions and configurations, the cache will be created in /etc/apk/cache.

This index is not needed after installation, so it can be removed. To do that, execute the clean command, or run rm -rf <location> for the cache location of you package manager tool.

Additionally, for apt-get, aptitude and apt some lock files are stored in /var/cache/apt/archives, which can also be removed safely. They are not removed by the clean command, so they need to be removed manually.

Alternatively, store the cache in a dedicated cache mount. A cache mount can be created by adding a flag --mount type=cache to the RUN command.
This will store the cache in a Docker volume, which will be persisted between builds making the build faster.

Also, each RUN instruction creates a new layer, and any changes made in one layer are not visible in the next. Thus, the cache should be removed in the same layer (i.e., the same RUN instruction) as the installation.

The following code incorrectly cleans the cache:

RUN apt-get install nginx
RUN apt-get clean

It should be written as:

RUN apt-get install nginx && apt-get clean

Resources

Documentation