# Dive
Dive is a terminal UI for exploring a [[Docker]] or [[Open Container Initiative (OCI)|OCI]] image one layer at a time. Created by Alex Goodman (wagoodman) in 2018, written in [[Go]], MIT licensed, and sitting at around 54k stars.
It answers a question the Docker CLI cannot: **not "how big is this image" but "which of your build steps made it big, and how much of that is waste".**
That distinction is the entire point. `docker history` gives you layer sizes. Dive gives you the file tree inside each layer, marks what each step added, changed, or removed, and then tells you how many bytes are sitting in the image doing nothing.
## What it shows you
- **Layer-by-layer file tree.** Pick a layer, see exactly which files it introduced. Files are marked added, modified, removed, or unchanged
- **Aggregated view.** Toggle between "what this layer changed" and "what the image looks like up to this layer"
- **Wasted space.** The number that matters. Bytes duplicated across layers, or deleted in a later layer while still shipping in an earlier one
- **Efficiency score.** An experimental percentage. Treat the wasted-bytes figure as the real signal and the score as a rough summary
- **`dive build -t tag .`** builds and analyses in one step, replacing your normal docker build while you are iterating
## The insight it makes visible
The thing most people learn from their first dive session: **`RUN rm` does not remove anything.**
Layers are immutable and additive. If step 4 installs a 300 MB toolchain and step 7 deletes it, the image still contains all 300 MB. Step 7 only adds a whiteout marker. Your `docker images` output shows the total, and nothing in the standard tooling tells you which layer is responsible or that the deletion accomplished nothing.
The classic offenders dive surfaces in about thirty seconds:
- Package manager caches (`apt` lists, `pip` cache, `npm` cache) installed in one layer and cleaned in another
- Build toolchains present in the final image because the cleanup came too late
- Source files, `.git` directories, and test fixtures copied in by a careless `COPY . .`
- The same dependency tree written twice by two different steps
The fix is nearly always the same shape: do the install and the cleanup **in the same `RUN`**, or use a multi-stage build so the build layers never reach the final image. Dive's value is that it tells you *which* line to fix, rather than leaving you to bisect a Dockerfile by hand.
## CI mode is the underrated half
Most people use dive interactively once, fix something, and forget it. The more durable use is the CI gate.
Set `CI=true` to skip the UI, and put a `.dive-ci` file in the repo:
```yaml
rules:
lowestEfficiency: 0.95
highestWastedBytes: 20MB
highestUserWastedPercent: 0.20
```
Now the build fails when someone reintroduces the bloat you removed last quarter.
This is worth doing for a reason beyond image size. Image bloat is the kind of problem that has **no natural feedback loop**: nobody notices a slow creep, everyone notices a 4 GB pull at 3am during an incident. A threshold in CI converts a thing you occasionally remember to check into a thing that cannot regress. That is the same argument as any other ratchet in a build pipeline, and it costs one YAML file.
Pick your thresholds from a measurement of the current image, not from the defaults. A threshold you cannot pass today gets disabled on day two.
## Installation
```bash
# macOS / Linux
brew install dive
# Arch
pacman -S dive
# Windows
winget install dive # or choco / scoop
# Go
go install github.com/wagoodman/dive@latest
# Docker (analyse an image without installing anything)
docker run --rm -it \
-v /var/run/docker.sock:/var/run/docker.sock \
wagoodman/dive:latest <your-image>
```
Debian/Ubuntu `.deb`, RHEL `.rpm`, Snap, and MacPorts packages are also published.
## Keybindings
| Key | Action |
|-----|--------|
| `Tab` | Switch between layer view and file tree |
| `Ctrl+F` | Filter files |
| `Ctrl+A` | Toggle aggregated layer view |
| `Space` | Collapse / expand a directory |
| `Ctrl+Space` | Collapse all directories |
| `Ctrl+C` / `Q` | Quit |
Configuration lives in `$XDG_CONFIG_HOME/dive/*.yaml`, `~/.config/dive/*.yaml`, or `~/.dive.yaml`. You can rebind keys, choose the container engine ([[Docker]] or [[Podman]]), and change which diff types are shown by default.
## Maintenance status (check this before adopting)
The README says "actively maintained". The repository says something more nuanced, and it is worth knowing before you put it in a pipeline:
- **Last release: v0.13.1, March 2025.** Roughly 17 months old at the time of writing
- **Last commits: May 2025**, and those are Dependabot dependency bumps rather than feature work
- **209 open issues**
- Not archived, and still the default recommendation everywhere
Read that as **stable and effectively finished**, not abandoned and not evolving. For a tool whose job is reading a format that has not changed, dormancy is a much smaller problem than it would be for, say, a security scanner. The risk to actually watch is compatibility drift with newer container engines and image formats, since nobody is currently shipping fixes for that. Pin the version in CI and verify it still reads your images after an engine upgrade.
## Where it stops
Dive tells you about **size and layer composition**. It does not tell you about vulnerabilities, licenses, or SBOM contents; that is a scanner's job. Interestingly, Alex Goodman went on to work on exactly that problem at Anchore with Syft and Grype, which is a reasonable hint about what pairs with this.
It also will not tell you whether a large image is a *problem*. A 2 GB image pulled once onto long-lived nodes may matter less than a 400 MB image pulled on every autoscale event. Measure the pull frequency before optimizing the bytes.
## References
- https://github.com/wagoodman/dive
- Docker multi-stage builds — https://docs.docker.com/build/building/multi-stage/
## Related
- [[Docker]]
- [[Containerization]]
- [[Open Container Initiative (OCI)]]
- [[Podman]]
- [[containerd]]
- [[LazyDocker]]
- [[Docker Desktop]]
- [[Docker Compose]]
- [[Terminal User Interface (TUI)]]
- [[Command Line Interface (CLI)]]
- [[Go]]
- [[Continuous Integration (CI)]]
- [[DevOps]]
- [[Software Supply Chain Security]]
- [[Kubernetes]]
- [[Homebrew]]