A powerful container debugging tool that injects a full-featured shell into any container - even minimal distroless images - making debugging seamless and powerful. No need to modify your containers or add debugging tools at build time.
- 🐳 Docker
- 🦭 Podman
- 🐋 Nerdctl
- 🔧 systemd-nspawn
- Inject a complete shell environment into running containers
- Install additional debugging tools with the built-in package manager
- Works with any container, including minimal and distroless images
- Zero container modifications required
- No build-time dependencies
Download the latest release into ~/.local/bin:
mkdir -p ~/.local/bin
curl -sL https://github.com/raphaelcoeffic/dive/releases/latest/download/dive-x86_64-unknown-linux-musl -o ~/.local/bin/dive
chmod +x ~/.local/bin/divePrerequisites:
- Rust toolchain (install via rustup)
# Build the binary
cargo build --release
# Optional: Install system-wide
cargo install --path .
# Optional: Build x86_64 static binary
export CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER=x86_64-linux-gnu-gcc
export CC=x86_64-linux-gnu-gcc
rustup target add x86_64-unknown-linux-musl
cargo build --target=x86_64-unknown-linux-musl
# Optional: Build arm64 static binary
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER=aarch64-linux-gnu-gcc
export CC=aarch64-linux-gnu-gcc
rustup target add aarch64-unknown-linux-musl
cargo build --target=aarch64-unknown-linux-muslThe release binaries embed a pre-built base image that includes the
package tool, and keep their state in $XDG_STATE_HOME/dive
(~/.local/state/dive by default). Both can be changed when building your own
binary, e.g. for offline environments where pkg cannot be used anyway.
Prerequisites (in addition to the Rust toolchain):
divev0.2.2 or later- network access while building (the base image build downloads Nix and nixpkgs)
- unprivileged user namespaces (on Ubuntu 24.04+, run
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0first)
# 1. Build the base image without the package tool.
# Writes base.tar.xz and base.sha256 into the repository root.
cargo run --bin build-img -- -a x86_64
# 2. Build dive with the base image embedded, using /var/local as the
# default state directory
CONFIG_STATE_DIR=/var/local \
cargo build --locked --release --features embedded_image --bin diveNotes:
CONFIG_STATE_DIRreplaces the default forXDG_STATE_HOME: state is kept in/var/local/diveand the base image in/var/local/dive/base-img. SettingXDG_STATE_HOMEat runtime still takes precedence. The directory must be writable by the user runningdive.- The package tool is only added to the base image when passing
-b <path to pkg>tobuild-img. The Makefile'sbase-imagetarget always adds it; to usemakewithout it, override both variables:make base-image pkg_bin= build_img_args="-a x86_64". - Extra packages can be added on top of the default ones (see
BASE_PACKAGESinsrc/lib.rs) with-P/--add-package, which can be repeated. Names are nixpkgs attribute names, e.g.cargo run --bin build-img -- -a x86_64 -P tshark -P python3. Withmake, append them tobuild_img_args:make base-image build_img_args="-a x86_64 -b <path to pkg> -P tshark". Insidedive,pkg listshows them as built-in packages. --features embedded_imageletsdiveinstall the base image from its own binary. Without it,divebuilds the base image on first run, which requires network access.--bin diveskips buildingpkg, which needs the program index generated by the Makefile (src/assets/programs.csv).- For static binaries or arm64, combine with the musl target options above
(
-a aarch64forbuild-img; building an arm64 base image on x86_64 requiresqemu-user-static).
# Debug a running container
dive <container-name>
# Run a single command instead of an interactive shell
dive <container-name> -- ss -tnp
# Or run directly through cargo
cargo run <container-name>A command given after -- runs with the same environment as the
interactive shell, but without the shell configuration (aliases, etc.).
Its output can be piped, and dive exits with its exit status. For shell
syntax, use -- zsh -c '...'.
# Debug a distroless container
dive my-distroless-app
# Debug a specific container by ID
dive 7d3f2c1b9e4a
# Capture the container's traffic into a local file
dive my-app -- tcpdump -i eth0 -w - > capture.pcapInside a dive session, you can add or remove packages:
# Add a package
pkg install iftop
# Or remove it
pkg remove iftop
# List installed packages
pkg list
# Search for packages
pkg search helixGithub rate limits
In case you hit Github's rate limit when installing a package:
* snmpd does not exist. Install net-snmp package? [y/N]
error:
… while updating the lock file of flake 'path:/nix/.cache/env-flake?lastModified=1765815061&narHash=sha256-gUo0/L8xm6/4Ky19XkxEmU3fQ0jfQbwJDI%2BI9cRfeCQ%3D'
… while updating the flake input 'flake-utils'
… while fetching the input 'github:numtide/flake-utils'
error: unable to download 'https://api.github.com/repos/numtide/flake-utils/commits/HEAD': HTTP error 403
response body:
{"message":"API rate limit exceeded for x.x.x.x. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)","documentation_url":"https://docs.github.com/rest/overview/resources-in-the-rest-api#rate-limiting"}
You should add your Github token (any read-only token will work) to the Nix configuration:
GITHUB_TOKEN="****your token****"
echo "access-tokens = github.com=${GITHUB_TOKEN}" >> ~/.local/state/dive/base-img/etc/nix.conf
The file will then look like this:
experimental-features = nix-command flakes
extra-nix-path = nixpkgs=github:nixos/nixpkgs/nixos-26.05
build-users-group =
sandbox = false
access-tokens = github.com=...
Contributions are welcome! Feel free to open issues and pull requests.
This project is licensed under the MIT License - see the LICENSE file for details.
- 🗑️ Add a clean-up command to remove local files
- 🐳 Support for more container runtimes
- 🔍 Enhanced inspection tools
- ⚡ Performance optimizations
Want to contribute to any of these features? Check out our Contributing section!
This project was inspired by and builds upon ideas from:
- Christian Brauner's article on Mounting into mount namespaces
- Ivan Velichko's guide on Docker: How To Debug Distroless And Slim Containers
- The Orbstack Debug feature and its approach to container debugging