dive: Docker Image Layer Explorer
Dive is a terminal tool for inspecting Docker image layers to find wasted space before you ship an image. Reach for it when you're chasing down why a Dockerfile produces a bloated image or want an automated size check in CI. Skip it if you only need a single size number now and then — `docker history` already gives you that without another binary to install.
What dive does and why image layers matter
Dive is a terminal UI that opens a Docker or OCI image and walks you through it layer by layer, showing exactly which files each layer added, changed, or removed. Layers matter because a Dockerfile that copies files in the wrong order, or cleans up in a later RUN instead of the same one, can leave gigabytes duplicated across layers that never actually leave the final image.
Exploring layers, files, and image efficiency
- ✓Layer-by-layer filetree navigation: select a layer on the left, see its contents merged with every prior layer on the right, move around with arrow keys.
- ✓Change tracking per layer: added, modified, and removed files are marked in the tree, either for the selected layer alone or aggregated up to that point.
- ✓Image efficiency score: an experimental percentage score plus a total wasted-byte count, estimating space lost to duplicated or leftover files across layers.
- ✓`dive build -t <tag> .` swaps in for `docker build` and drops you straight into analyzing the image you just built.
- ✓CI mode (`CI=true dive <image>`) skips the UI and returns pass/fail exit codes based on rules in a `.dive-ci` file.
- ✓Multiple image sources via `--source`: the Docker engine, a Docker tar archive on disk, or Podman.
- ✓Fully remappable keybindings and a config file for filetree pane width, default collapse state, and file-attribute display.
Installing dive on Linux, macOS, and Windows
On Debian and Ubuntu, the README's install script pulls the latest release tag from the GitHub API and installs the matching `.deb` with `apt install`; RHEL and CentOS follow the same pattern with an `.rpm`. A snap package exists too, but the README warns against it if Docker itself came from `apt-get`, since it can break your existing Docker daemon (see issue #546). Arch Linux ships dive in the official extra repository, installable with `pacman -S dive`. On macOS, `brew install dive` or `sudo port install dive` (MacPorts) both work, or you can grab a Darwin binary from the releases page. On Windows, Chocolatey (`choco install dive`), Scoop (`scoop install main/dive`), and winget (`winget install --id wagoodman.dive`) are all supported, alongside a direct download. Go developers can run `go install github.com/wagoodman/dive@latest` (Go 1.10+), though the README notes this skips proper version embedding for `dive -v`. Nix, NixOS, x-cmd, and a Docker image (`docker pull docker.io/wagoodman/dive` or `ghcr.io/wagoodman/dive`) round out the options.
Analyzing your first Docker image with dive
Run `dive <your-image-tag>` against anything already pulled or built locally — `dive nginx:latest` opens the TUI straight away. If you're building fresh, `dive build -t <some-tag> .` replaces your normal `docker build` call and drops you into the analysis the moment the build finishes. Inside the UI, Tab switches between the layer list and the file tree, Ctrl+F filters files, and the arrow keys (or vim-style j/k) move around. When running dive via the Docker container itself, you mount the Docker socket (`-v /var/run/docker.sock:/var/run/docker.sock`); if your local Docker API version doesn't match, set `DOCKER_API_VERSION` explicitly, and on an alternative runtime like Colima, export `DOCKER_HOST` first so dive can find local images. For a scripted check instead of the UI, set `CI=true` before the command.
Finding wasted space and shrinking image size
- •Multi-stage Dockerfile debugging: spot which RUN or COPY step actually inflates the final image instead of guessing from `docker history`.
- •Pre-merge size gate: wire `CI=true dive` with a `.dive-ci` file into your CI/CD pipeline so a build fails when wasted space or efficiency crosses your threshold.
- •Base image comparisons: see how much of the bloat comes from a base image's own layers versus your app layers.
- •Cleanup audits on legacy Dockerfiles nobody wants to touch, to find files that got copied in and never removed in a later layer.
Strengths
- ✓Layer-level filetree beats scrolling through `docker history` output when you need to see which specific files a layer touched.
- ✓`dive build -t <tag> .` collapses "build then inspect" into one command instead of two.
- ✓CI mode turns image bloat into a scriptable pass/fail check instead of a manual eyeball.
- ✓Supports Podman and Docker tar archives via `--source`, not just a live Docker daemon.
- ✓Keybindings and UI panes are configurable through a YAML file instead of being hard-coded.
Known limitations and beta caveats
- △The README labels dive "beta quality" — a signal from the maintainer, not just cautious phrasing.
- △The efficiency score is explicitly called experimental.
- △Snap installation is flagged as risky if Docker was installed via `apt-get`, since it can break the existing Docker daemon (see issue #546 in the README).
- △Building via `go install` skips version embedding, so `dive -v` won't show a proper version string.
- △Analyzing against the Docker engine requires mounting the Docker socket, which some CI runners and locked-down environments won't allow.
Other ways to inspect Docker image layers
Frequently asked questions about dive
Dive is free and open source, released under the MIT license, with its source hosted on GitHub.
Dive supports Podman as an image source alongside Docker: pass `--source podman` (Linux only, per the README) instead of relying on the default Docker engine source.
Dive runs in CI mode when you set `CI=true` before the command, e.g. `CI=true dive <your-image>`. It skips the interactive UI and returns a pass/fail exit code based on rules in a `.dive-ci` file (or a path set via `--ci-config`).
Dive's image efficiency score is an experimental percentage estimate of how much of an image's size is wasted space — duplicated files, files moved between layers, or files not fully removed — shown alongside the total wasted bytes.
Dive's keybindings and UI (pane width, default collapse state, file attributes) are configurable through a YAML config file that dive looks for in locations like `~/.dive.yaml` or `~/.config/dive/`.
Dive needs the Docker socket (`/var/run/docker.sock`) mounted because it talks to the Docker engine API to pull image layer data when using the default Docker source — that's why the Docker-based install commands mount it explicitly.
The problem it solves
Dockerfiles pick up cruft through iterative edits — an apt cache that never gets cleared, a build artifact copied in before a later RUN deletes it, a base image swapped without checking what changed — and none of that shows up in a plain image size number. `docker history` lists layer sizes but not which files live in them, so tracking down where the bytes went usually means guesswork or trial-and-error rebuilds. Dive opens the image and shows the actual file tree per layer, so that specific waste is visible in one pass.
Who should try it — and who should skip
Try dive if you maintain a Dockerfile that's grown organically over multiple iterations and want to see exactly where the bytes are going before you tackle container optimization by guesswork, or if you want an automated size gate in CI instead of a human eyeballing `docker images`. Skip it if you only need a single size number occasionally — `docker history` or `docker images` already answers that without installing another binary — or if your environment can't mount the Docker socket at all.
Related repositories
Curious whether dive is right for you?
Let ChatGPT, Claude, or Perplexity look into it — click below and see what AI actually says about dive.
