When building Docker images, caching lets you speed up rebuilding images.
But this has a downside: it can keep you from installing security updates from your base Linux distribution.
If you cache the image layer that includes the security update… you’re not getting new security updates!
There are a number of ways you can try to balance caching with getting security updates, with different tradeoffs.
In this article we’ll cover:
- Caching by default, with recurring rebuild and redeploys.
- Deliberately breaking caching.
- Caching during development, never caching in production builds.
Recap: the problem
I’ve written a separate article about this problem but here’s a recap.
Consider the following Dockerfile
:
FROM python:3.11-slim
RUN apt-get update && apt-get -y upgrade
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY myapp .
ENTRYPOINT ["python", "-m", "myapp"]
The first time you build it, you will get security updates installed via apt-get
.
If you’re using caching, when you rebuild the image those apt-get
commands won’t get rerun; instead, the cached version will be used.
Time passes, and now you’re months behind on security updates.
Oops.
Note: Outside any specific best practice being demonstrated, the Dockerfiles in this article are not examples of best practices, since the added complexity would obscure the main point of the article.
Need to ship quickly, and don’t have time to figure out every detail on your own? Read the concise, action-oriented Python on Docker Production Handbook.
Solving the problem
When considering alternative solutions, there are multiple goals to balance:
- Timely security updates.
- Fast rebuilds when building the Docker image on developer machines.
- Fast rebuilds when building the production Docker image in CI, as part of the production pipeline.
- Minimizing complexity.
Let’s consider different approaches and how they do on these goals.