Back to Blog
DevOpsJuly 6, 20264 min read

Docker image size reduction: How to analyze layers with Dive

Reduce docker image size by using the Dive tool for layer analysis. Learn how to identify and remove non-essential files to optimize your containers.

dockercontainersdevopsperformanceoptimizationdive

We’ve all been there: you push a "small" microservice image, only to find the CI pipeline hanging for minutes while it uploads a 1.2GB blob to the registry. I once spent an entire afternoon trying to figure out why a simple Node.js container ballooned to nearly 900MB. It turned out to be a combination of cached npm packages and a stray node_modules folder copied during a build step.

If you’re struggling with docker image size, you aren't alone. Most of the time, the issue isn't your application code—it's the accumulation of unnecessary files across layers.

Why Layer Analysis Matters

Docker images are built as a series of read-only layers. Every RUN, COPY, and ADD command in your Dockerfile adds a new layer. If you remove a file in a later step, it doesn't actually disappear from the image; it’s just hidden by a whiteout file. The data is still there, taking up space in your registry and slowing down your pull times.

Before diving into complex optimizations, you need to see what’s actually inside those layers. This is where the dive tool becomes indispensable.

Inspecting Layers with Dive

Dive is a terminal-based tool that lets you explore every layer of a Docker image. It shows you exactly what changed in each step and, more importantly, how much space each layer consumes.

To get started, install it (on macOS, it’s just brew install dive) and run it against your image:

Bash
dive your-image-name:tag

The interface is split into two panes. The left pane shows your layers; the right pane displays the file tree for the currently selected layer. You can navigate the layers and see files marked with A (added), M (modified), or R (removed).

Identifying Bloat

When I'm analyzing an image, I look for these common culprits:

  1. Package manager caches: apt-get cache or npm cache folders.
  2. Build artifacts: Source code, .git directories, or temporary build tools that aren't needed at runtime.
  3. Redundant copies: Files copied into the image that are later deleted or overwritten.

If you find that your image is still bloated despite your best efforts, you might need to rethink your build strategy. I often use Docker Multi-Stage Builds: Reduce Image Size and Harden Security to ensure that only the final binary or transpiled assets end up in the production image.

How to Reduce Docker Image Size

Once you've identified the heavy layers, you can start cleaning them up. Here’s a typical workflow for optimization:

  • Combine commands: Chain your RUN commands with && to ensure that cleanup happens in the same layer as the installation.
  • Use .dockerignore: Prevent unnecessary files like local logs, node_modules, or .env files from ever entering the build context.
  • Clean up caches: If you are using apt, always include rm -rf /var/lib/apt/lists/* in the same RUN step.

If you are dealing with complex environments, managing these configurations can become a chore. If you need help streamlining your infrastructure, I provide CI/CD Pipeline & Docker Containerization services to help you ship faster.

Comparison: Standard vs. Optimized Build

Sometimes it’s helpful to see what a "clean" layer structure looks like compared to a messy one.

FeatureMessy BuildOptimized Build
Layer countHigh (15+)Low (5-8)
Cache usageInefficientOptimized via BuildKit
CleanupSeparate RUN stepInline && rm
Final sizeLarge (500MB+)Small (50MB-100MB)

The "Wrong Turn" Trap

I once tried to fix an image by simply deleting a large directory in a new RUN command at the end of the Dockerfile. My image size didn't budge. I was confused until I learned about the layer filesystem—the data was still sitting in the previous layers, just "hidden."

If you find yourself stuck in a cycle of trial-and-error with your Dockerfile, check out these tips on Docker Image Optimization: Reduce Build Size and Speed Up Deployments to understand how to structure your layers for better caching.

FAQ

Does using Dive affect my image? No, Dive is a read-only analysis tool. It doesn’t modify your image or your Dockerfile.

Why is my image still large even after deleting files? Remember that Docker layers are cumulative. If you add a 200MB file in Layer 2 and delete it in Layer 3, the image size remains the same because Layer 2 still exists. You must perform the addition and deletion in the same RUN command.

What is the best way to handle build-time dependencies? Multi-stage builds are the gold standard. Perform your compilation in a "builder" stage and copy only the necessary artifacts to the "runner" stage.

Optimizing images is rarely a one-time task. As your application grows, you'll need to periodically audit your layers. I’m still refining my own base images, and sometimes I find a better way to structure a multi-stage build that saves me another 20MB. Keep experimenting with your Dockerfile and don't be afraid to break things in development.

Similar Posts