Docker Tip #100: Should You Use Image Digests in Your Dockerfile?
Adding a digest reference to your images can make builds more predictable, here's a few pros and cons of using them.
Prefer video? Here’s a recorded version of this tip on YouTube which covers this topic.
For example you can define this in your Dockerfile
:
FROM python:3.12.7-slim-bookworm
But you can also add an optional image digest:
FROM python:3.12.7-slim-bookworm@sha256:d2ead4f6f2ac4b88e44b45a06caea68ad3e2280c0028afcf136e9edfe28c2346
Without the digest, if you build that image today or 3 months from now you’ll likely get a slightly different image. Perhaps different security patches will be applied.
Most of the time things will still work and you’ll end up with a more secure image as you build it in the future but sometimes it can break things.
Mutable Image Tags Can Break Things
Python 3.12’s standard library got rid of the setuptools
package but the
official Docker image still pip installed it for you so it was available.
However, back in August
2024 they removed it.
Long story short, that broke my example Django starter
app for new folks
starting to use the project until I went back and explicitly installed
setuptools
within the project. It broke because I didn’t digest the Python
image tag and it changed over time.
Pros and Cons
On paper it seems good to always use it for more predictable builds but you can also make a case to avoid it. Ultimately it’s up to you but here’s a few advantages and disadvantages:
- Pros
- More predictable and reproducible builds
- If something breaks you can pin point when and why
- Easier to track changes from a security audit perspective
- Each time you change the digest you can track it in a git commit
- More likely to avoid supply chain attacks
- If an image repo got compromised and a bad actor pushed a malicious tag, you’d be safer due to having a digested image before it got compromised
- More predictable and reproducible builds
- Cons
- Sometimes living on the edge makes sense for a project
- If a project is meant to be kept up to date and something breaks it lets you to react to the breaking change sooner with less effort
- Certain security tools sometimes have trouble scanning images with digests
- I’ve noticed this in the past with Snyk silently failing to scan images but that may have changed by now
- Sometimes living on the edge makes sense for a project
With that said, for apps running in production I tend to digest them but I keep them undigested in my example starter apps because I want to be notified of breaking changes in a way that doesn’t involve me continuously updating the digests.
Technically you can automate that with tools and scripts. For example, here’s how you can find the latest digest for a specific image tag using the Docker CLI and standard Unix tools:
$ docker manifest inspect python:3.12.7-slim-bookworm -v | grep digest | head -1
"digest": "sha256:d2ead4f6f2ac4b88e44b45a06caea68ad3e2280c0028afcf136e9edfe28c2346",
# Alternatively, if you have `jq` installed you can parse this a bit easier:
$ docker manifest inspect python:3.12.7-slim-bookworm -v | jq -r ".[0].Descriptor.digest"
sha256:d2ead4f6f2ac4b88e44b45a06caea68ad3e2280c0028afcf136e9edfe28c2346
Depending on when you run that command, your result may be different than mine.