docker debug

Debugging Distroless and Slim Images with docker debug

A distroless image (Choosing a Base Image) has no shell and no ls, so docker exec has nothing to run. docker debug attaches a toolbox (a shell, curl 3,008 , vim, htop 386,022 and any Nix 17,784 package on demand) to a container or image without changing it. It is proprietary and ships only with Docker Desktop 514 , free for all users since Desktop 4.50; Engine on Linux has no such command, and the request to add it (docker/roadmap issue #893, February 2026) is still open. On Engine, the same idea works with namespaces:

No shell in a distroless container, and two ways inShell
docker debug l3-dl 2>&1 | head -1
docker run -d --name l3-dl gcr.io/distroless/nodejs24-debian13 \
  -e 'require("http").createServer((q, s) => s.end("ok\n")).listen(3000)' >/dev/null
docker exec l3-dl sh 2>&1 | grep -o 'exec: .*'
docker run --rm --pid container:l3-dl --network container:l3-dl busybox:1.38 \
  sh -c 'ps | head -2 | cut -c 1-50; netstat -tln | tail -1; ls /proc/1/root/nodejs/bin'
R=https://github.com/iximiuz/cdebug/releases/download/v0.0.19
curl -Ls $R/cdebug_linux_amd64.tar.gz | tar xz cdebug
./cdebug exec --rm l3-dl sh -c 'wget -qO- localhost:3000; which wget; ls / | head -6' \
  | tr '\n' ' '; echo
docker rm -f l3-dl >/dev/null
Output
docker: unknown command: docker debug
exec: "sh": executable file not found in $PATH
PID   USER     TIME  COMMAND
    1 root      0:00 {MainThread} /nodejs/bin/node
tcp        0      0 :::3000                 :::*                    LISTEN
node
ok /.cdebug-258fda0d/bin/wget bin boot dev etc home lib

The BusyBox 65,982 container joined the target's PID and network namespaces, so its ps sees Node.js 2,131 as PID 1, its netstat sees port 3000, and /proc/1/root exposes the target's files. cdebug 1,675 (github.com/iximiuz/cdebug (https://github.com/iximiuz/cdebug 1,675 ), Apache-2.0) automates this: it starts BusyBox in the target's namespaces, then chroots into the target's root with its tools in a hidden /.cdebug-* directory on the PATH, so ls / shows the distroless filesystem, yet wget works.

A debug container borrows the target's namespaces, not its image
A debug container borrows the target's namespaces, not its image

Kubernetes 5,150 builds this pattern in as kubectl 5,150 debug (Kubernetes). Treat debug access in production like shell access.