netshoot: entering a container's network namespace instead of installing tools in it
a Docker + Kubernetes network trouble-shooting swiss-army container
At a glance
- What is it?
- netshoot is a container image packed with network debugging tools that you attach to an existing network namespace. It is useful when the workload you need to inspect has no shell, no tcpdump and no way to add either.
- Who is it for?
- Adopt netshoot when you debug containers you cannot modify, when you need tcpdump inside a pod's namespace, or when a node-level session has to happen without installing packages on the node. Do not adopt it as a permanent sidecar for routine monitoring, and do not treat it as a minimal image: the Dockerfile installs a large package set from Alpine edge repositories on top of a base of alpine:3.24.1.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 7 days ago.
- What is it written in?
- Mainly Shell, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem netshoot solves: tools you cannot install
Docker and Kubernetes give every container its own network namespace, which means its own interfaces, routes and IP stack. The README states this as the premise of the whole project. The practical consequence is that when a pod cannot resolve a service name, the diagnostic tools you want are usually in an image that has none of them, and the image is frequently a distroless or scratch build with no shell at all.
netshoot takes the opposite route. Instead of adding tools to the workload, you start a second container that joins the first one's namespace. The README describes the benefit directly: debug a container without installing tools into its image, debug a host without installing anything on it, debug in Kubernetes as an ephemeral container, throwaway pod, or sidecar. Nothing inside the target process changes, and nothing is written to its filesystem.
That makes it a fit for platform and SRE work where the workload is immutable by policy. It is a poor fit for anyone who wants a small, always-on observability agent. netshoot is a session you open, use and close.
How namespace sharing actually works in the Docker and Kubernetes paths
The mechanism is namespace entry, not process injection. Under Docker, --net container:<container_name> makes the new container share the target's network namespace, so ip addr, ip route and tcpdump inside netshoot see exactly what the target sees. Under Kubernetes, kubectl debug creates an ephemeral container in a running pod, which the README describes as non-destructive.
There is a third path for bridge networks that the README documents separately. You mount /var/run/docker/netns into a privileged netshoot container and then run nsenter --net=/var/run/docker/netns/<id> sh. That is a heavier grant: privileged mode plus a host path mount. It is the option to argue about in review, because the same access that lets you inspect a bridge namespace also removes most of the isolation the container had.
The image itself is built in two stages. A debian:stable-slim fetcher stage runs build/fetch_binaries.sh to download ctop, calicoctl, termshark, grpcurl and fortio, which are then copied into an alpine:3.24.1 final stage. The runtime stage appends Alpine edge main, testing and community repositories before running apk add on a long package list that includes tcpdump, tshark, nmap, iperf3, mtr, trippy, drill, conntrack-tools, nftables and scapy. Two consequences follow from that layout. The image is large by design, and it depends on edge repositories, which move faster than stable ones. Pinning a digest rather than a floating tag is the only defence the repository offers against that.
Installing netshoot and running a first capture
There is nothing to install on the host beyond Docker or kubectl. The image is pulled on first use. The README's Quick Start gives three entry points, and the Docker one is the shortest path to a real result.
Start a container you want to inspect, then attach netshoot to its namespace. The prompt that appears is zsh, since the image ships oh-my-zsh and a zshrc.
# Share a running container's network namespace
docker run -it --net container:<container_name> nicolaka/netshootInside that session, confirm you are looking at the right interfaces before capturing anything. ip addr should list the target's addresses, not a fresh container's.
ip addr
ip route show
tcpdump -i eth0 -nn host <ip> and port 80For Kubernetes, the equivalent is an ephemeral container. The README gives this exact command.
kubectl debug <pod> -it --image=nicolaka/netshootIf you want the session to disappear when you exit, the throwaway pod form is what the README shows.
kubectl run tmp-shell --rm -i --tty --image nicolaka/netshootAdding --overrides='{"spec": {"hostNetwork": true}}' to that command puts the shell on the node's network namespace, which is how you capture traffic the pod networking layer never sees. The repository also ships configs/netshoot-sidecar.yaml for the sidecar pattern, applied with kubectl apply -f configs/netshoot-sidecar.yaml and entered with kubectl exec -it <pod> -c netshoot -- zsh. There is a separate kubectl-netshoot plugin, maintained in a different repository, that wraps these into subcommands such as kubectl netshoot debug node/my-node.
What a DNS failure looks like from inside netshoot
The README's DNS scenario is the clearest demonstration of why namespace entry matters. The sequence starts with cat /etc/resolv.conf to see which server the container is actually using, which is often not the one you assumed. From there, drill kubernetes.default.svc.cluster.local resolves a cluster name, and drill @10.96.0.10 kubernetes.default.svc.cluster.local queries the cluster DNS directly, bypassing resolv.conf.
The step that earns its place is tcpdump -i eth0 -n port 53. Seeing whether packets leave the pod at all separates two failures that look identical from the application side. The README makes that distinction explicit with drill -V 5 my-service.my-namespace.svc.cluster.local: NXDOMAIN and timeout have different root causes, and only the wire tells you which one you have.
The other scenarios follow the same shape. For latency, mtr --report --report-cycles 10 gives per-hop numbers and trip gives an interactive TUI traceroute. For throughput, iperf3 -s on one pod and iperf3 -c <pod-A-ip> -t 30 on another. For reachability, nc -vz <host> <port>, nmap -p 8080-8090 <host> and tcptraceroute <host> <port>. For TLS, openssl s_client -connect <host>:443 </dev/null piped into openssl x509 -noout -text. Each of these assumes the tool is present in the namespace you are inspecting, which is the assumption netshoot exists to satisfy.
Where netshoot is the wrong tool
The privileged bridge-namespace recipe is the sharpest limitation. It requires --privileged and a mount of /var/run/docker/netns, and the README documents it without a softer alternative. On a shared host, that is a meaningful expansion of what the session can reach. The host-network Kubernetes variant has the same character: it is exactly what makes node-level capture possible and exactly what most admission policies are written to prevent.
The second limitation is the image itself. Alpine edge repositories are enabled in the Dockerfile, and the package list is broad enough to include nmap, scapy, calicoctl and strace. That is the point of a swiss-army image, but it means netshoot is not a minimal attack surface and should not be left running as a permanent sidecar on every pod. Use it for a session, then let it exit.
The third is scope. netshoot operates inside a network namespace. If your problem is a crashed process, a disk-full node or an application bug that never touches the network, the tools in this image will not tell you anything the workload's own logs would not. It is a network diagnostic container, and the README frames it that way throughout.
Finally, the repository does not publish releases. The Makefile defines VERSION=0.1 and targets build-x86, build-arm64, build-all and push, so the practical question of which tag you are running is answered by the registry, not by release notes.
netshoot against busybox and against a purpose-built debug image
The comparison people reach for is busybox, and the difference is the tool inventory rather than the mechanism. busybox provides a small shell and a handful of applets, so it can resolve a name with nslookup and open a socket with nc, but it has no tcpdump, no tshark, no mtr, no iperf3 and no nmap. When the question is what is on the wire rather than whether a port answers, busybox stops and netshoot continues.
A second alternative is the cluster's own debug tooling. kubectl debug can attach an ephemeral container with any image you choose, and the README builds on that command rather than replacing it. If your platform team already maintains a hardened debug image with an approved package set, netshoot's value is the specific inventory in its Dockerfile: drill, trippy, termshark, grpcurl, fortio, swaks, conntrack-tools, nftables and the rest, assembled and kept in one place. If you need only one of those tools, pulling netshoot to get it is a large download for a small job.
The kubectl-netshoot plugin sits between the two. It does not add tools; it wraps the kubectl debug and kubectl run invocations into subcommands, which removes the flag memorisation and not much else.
Maintenance, licence and the cost of keeping it current
The last push to the default branch was on 2026-07-01, and the repository is not archived. There are no retrieved releases, so upgrades are driven by image tags rather than versioned changelogs. The Makefile's VERSION=0.1 is a build variable, not a published release number, and the push target sends ${IMAGENAME}:${VERSION} to the registry.
That combination sets the upgrade cost. Because the runtime stage pulls from Alpine edge and runs apk upgrade during the build, a rebuild can pick up newer packages than the last image you tested, and nothing in the repository records the difference. Teams that need reproducibility should pin a digest and rebuild deliberately rather than track a moving tag.
netshoot is licensed Apache-2.0, and the LICENSE file is at the repository root. That covers netshoot's own files. It does not cover the bundled binaries: ctop, calicoctl, termshark, grpcurl and fortio are downloaded in the fetcher stage from their own projects, and the Alpine packages carry their own licences. If you redistribute the image inside a product, the notices for those components are your responsibility to assemble. That is a packaging question for your legal team, not something this repository answers.
Editorial conclusion
Adopt netshoot when you debug containers you cannot modify, when you need tcpdump inside a pod's namespace, or when a node-level session has to happen without installing packages on the node. Do not adopt it as a permanent sidecar for routine monitoring, and do not treat it as a minimal image: the Dockerfile installs a large package set from Alpine edge repositories on top of a base of alpine:3.24.1. Before rollout, check how your cluster treats ephemeral containers, confirm the image tag you pin, and decide whether the privileged and host-network variants are acceptable under your policy.
Frequently asked questions
What is netshoot?
It is a container image for Docker and Kubernetes network troubleshooting, built from alpine:3.24.1 with a large set of network tools installed. You run it attached to an existing network namespace rather than inside the workload you are diagnosing.
How do I use netshoot with Docker?
The README's Quick Start gives docker run -it --net container:<container_name> nicolaka/netshoot to share a running container's namespace, and docker run -it --net host nicolaka/netshoot to use the host's. Once inside, tools such as tcpdump, drill and ip see the same interfaces and routes as the target.
What is a netshoot pod in Kubernetes?
The README shows two forms: an ephemeral container added to a running pod with kubectl debug <pod> -it --image=nicolaka/netshoot, and a throwaway pod created with kubectl run tmp-shell --rm -i --tty --image nicolaka/netshoot. A sidecar variant is provided in configs/netshoot-sidecar.yaml.
Is nicolaka/netshoot safe to run?
The README documents options that grant broad access, including a privileged container with /var/run/docker/netns mounted and a Kubernetes pod override setting hostNetwork to true. The image also installs a wide package set from Alpine edge repositories. Whether that is acceptable depends on your own host and cluster policy, which the repository does not address.
How is netshoot different from busybox for network debugging?
Both give you a shell in a namespace, but busybox ships a small applet set. netshoot's Dockerfile installs tcpdump, tshark, termshark, nmap, mtr, trippy, iperf3, conntrack-tools and others, so it covers packet capture and protocol dissection that busybox does not.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/nicolaka-netshoot)