I was trying to monitor traffic between containers in an internal Docker network and started down the path of writing Python with the Docker SDK to query /proc but thought there had to be an easier way. There are many great monitoring tools already written that I should be able to use. My problem was that they aren’t installed in the containers (and I don’t want to rebuild the containers), but they are already on my host computer. Is there a way to use them?

My usual approach is to use docker exec -it <CONTAINER> <COMMAND> to invoke a command inside of a container, but this technique is limited to running a command already installed within the container. Many of the slimmer distributions (e.g., alpine) don’t include these command intentionally to keep the image sizes down. While one could just install the command via apk, this post offers a simpler way and gives some insight into how Docker works.

nsenter

Enter nsenter (“namespace enter”). This command runs a command from the host in the namespace for the indicated process. Without going into any detail as to how it works, Docker gives the illusion of a container having its own network stack using network namespaces (see the man pages for nsenter for other namespaces).

To use, first find your container in the list of containers,

$ docker ps

Get the process id (PID) for the container,

$ docker inspect -f '.State.Pid <CONTAINER>'

Then, run your host’s command ( below) in the container.

$ sudo nsenter -t <PID> -n <COMMAND>

Example: Running iftop

In this example I am running iftop, a network monitoring tool, in the container with the PID 25455. Note that iftop is not installed in the Alpine container being monitored but is running from the host within the container’s network namespace.

$ sudo nsenter -t 25455 -n iftop

Other Namespaces

As a sanity check, I tried a few process- and filesystem-based commands to see if they run in the container’s namespaces, and they appear to. The -a option to nsenter invokes the command in all of the container’s namespaces.

For ps we see a very limited number of process in the container. It’s clearly running in the container’s and not the host’s context:

$ sudo nsenter -t 25455 -a ps -aef
PID   USER     TIME  COMMAND
    1 root      0:00 /bin/sh
   34 root      0:00 ps -aef

ls returns the directories present in the container, not that of the host – great!

$ sudo nsenter -t 25455 -a ls /
bin    dev    etc    home   lib    media  mnt    opt    proc   root   run    sbin   srv    sys    tmp    usr    var

References

I found this blog post helpful in understanding this command.