Container images are one of the items that makes up a “container.” In most cases container images use a base image (e.g., Alpine, Ubuntu, etc.), and then one or more application-specific layers are added on top of that. There are numerous documented best practices for optimizing container images, and these best practices result in smaller images, less network traffic, and a reduction in container creation time.
Unfortunately in practice, I’ve seen numerous cases were these best practices weren’t followed. I’ve come across Dockerfiles that used dozens of RUN commands, didn’t take advantage of multistaged builds, didn’t optimize for image layer re-use, etc. When I’ve encountered these types of issues, I’ve always taken it upon myself to work with the author to refactor the build instructions, and to educate them on best practices. The hadolint project maintains an excellent set of Docker best practice rules, which I highly suggest reviewing if you haven’t already.
When situations pop up where I need to dig into a container image, I always turn to my good buddy dive. This amazing little utility allows you to analyze a container image in a console TUI. Exploring a container image with dive is super easy. Type dive into your terminal, pass the container image you want to explore as an argumnet, and the TUI will be displayed:
$ dive nginx:latest
One of the most useful screens in the TUI is the image details pane:
Image name: nginx
Total Image size: 142 MB
Potential wasted space: 3.8 MB
Image efficiency score: 98 %
This shows the image size, how much space is wasted, and the containers efficiency score. The efficiency score is super helpful for understanding where the image lies on the efficiency spectrum, and if further analysis would be beneficial. Dive was developed with CI in mind. You can run dive with the “–highestUserWastedPercent” and “–highestWastedBytes” arguments as part of a CI pipeline. If the image that is created doesn’t past muster, you can fail the build until someone reviews the build instructions.
If you come across an image with a poor efficiency score while debugging an issue, you can review the container’s build statements (Dockerfiles, JIB XML stanzas, etc.) in source control, or generate these on the fly with the docker history command:
$ docker history --no-trunc nginx:latest
I love debugging problems, especially ones where the end result is added efficiency. Giddie up!