Minimal image for nsenter
to namespaces of PID 1
- mnt
- uts
- net
- ipc
To achieve the above with the basic alpine image you would enter:
$ docker run -it --rm --privileged --pid=host alpine:edge nsenter -t 1 -m -u -n -i sh
/ #
Unfortunately, however, there is an outstanding issue that prevents specifying the target pid.
With this image, you can simply run the following:
$ docker run -it --rm --privileged --pid=host justincormack/nsenter1
/ #
nsenter
allows you to enter a shell in a running container (technically into the namespaces that provide
a container's isolation and limited access to system resources). The crazy thing is that this image allows
you to run a privileged container that runs nsenter for the process space running as pid 1. How is this useful?
Well, this is useful when you are running a lightweight, container-optimized Linux distribution such as
LinuxKit.
Here is one simple example: say you want to teach a few people about Docker networking and you want to
show them how to inspect the default bridge network after starting two containers using ip addr show
;
the problem is if you are demonstrating with Docker for Mac, for example, your containers are not running on
your host directly, but are running instead inside of a minimal Linux OS virtual machine specially built for
running containers, i.e., LinuxKit. But being a lightweight environment, LinuxKit isn't running sshd
, so
how do you get access to a shell so you can run nsenter
to inspect the namespaces for the process running as pid 1?
Well, you could run the following:
$ screen ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/tty
Docker for Mac does expose a screen session to attach to, but it's a bit less than ideal if you're not familiar with screen. It's not a big deal, but it's not optimal and it's also very specific to Docker for Mac. Since we're already running Docker the general solution is ideal in this case:
$ docker run -it --rm --privileged --pid=host justincormack/nsenter1
/ # ip a
256: vethb72bfa3@if255: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue master docker0 state UP
link/ether 7a:41:32:02:63:7c brd ff:ff:ff:ff:ff:ff
inet6 fe80::7841:32ff:fe02:637c/64 scope link
valid_lft forever preferred_lft forever
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 brd 127.255.255.255 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 02:50:00:00:00:01 brd ff:ff:ff:ff:ff:ff
inet 192.168.65.3/24 brd 192.168.65.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::49e8:1c10:4c64:c980/64 scope link
valid_lft forever preferred_lft forever
...
Have fun!