Skip to content
raphaelcoefficPublic

About

A powerful container debugging tool

Topics

Resources

Stars

13 stars

Watchers

1 watching

Forks

Latest commit

 

History

77 Commits

Folders and files

Repository files navigation

dive - a container debugging tool

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.

Features

Runtime Support

  • 🐳 Docker
  • 🦭 Podman
  • 🐋 Nerdctl
  • 🔧 systemd-nspawn

Core Features

  • 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

Installation

Installing from release binary

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/dive

Building from source

Prerequisites:

  • 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-musl

Custom builds

The 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):

  • dive v0.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=0 first)
# 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 dive

Notes:

  • CONFIG_STATE_DIR replaces the default for XDG_STATE_HOME: state is kept in /var/local/dive and the base image in /var/local/dive/base-img. Setting XDG_STATE_HOME at runtime still takes precedence. The directory must be writable by the user running dive.
  • The package tool is only added to the base image when passing -b <path to pkg> to build-img. The Makefile's base-image target always adds it; to use make without 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_PACKAGES in src/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. With make, append them to build_img_args: make base-image build_img_args="-a x86_64 -b <path to pkg> -P tshark". Inside dive, pkg list shows them as built-in packages.
  • --features embedded_image lets dive install the base image from its own binary. Without it, dive builds the base image on first run, which requires network access.
  • --bin dive skips building pkg, 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 aarch64 for build-img; building an arm64 base image on x86_64 requires qemu-user-static).

Usage

# 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 '...'.

Examples

# 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.pcap

Package Tool

Inside 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 helix

Troubleshooting

Github 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=...

Contributing

Contributions are welcome! Feel free to open issues and pull requests.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Roadmap

Short term

  • 🗑️ Add a clean-up command to remove local files

Coming later

  • 🐳 Support for more container runtimes
  • 🔍 Enhanced inspection tools
  • ⚡ Performance optimizations

Want to contribute to any of these features? Check out our Contributing section!

Acknowledgments

This project was inspired by and builds upon ideas from:

About

A powerful container debugging tool

Topics

Resources

Stars

13 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages