Running a Command from a Host in a Docker Container (nsenter)
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 (
$ 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.