Introducing nsenter
nsenter
is a small tool allowing to enter
into n
ames
paces. Technically, it can enter existing namespaces, or spawn a process into a new set of namespaces. “What are those namespaces you’re blabbering about?” They are one of the essential constituents of containers. The short version is: with nsenter
, you can get a shell into an existing container, even if that container doesn’t run SSH or any kind of special-purpose daemon.
Where do I get nsenter
?
Check jpetazzo/nsenter on GitHub. The short version is that if you run:
docker run -v /usr/local/bin:/target jpetazzo/nsenter
This will install nsenter
in /usr/local/bin
and you will be able to use it immediately. nsenter
might also be available in your distro (in the util-linux
package).
How do I use it?
First, figure out the PID of the container you want to enter:
PID=$(docker inspect --format {{.State.Pid}} <container_name_or_ID>)
Then enter the container:
nsenter --target $PID --mount --uts --ipc --net --pid
You will get a shell inside the container. That’s it. If you want to run a specific script or program in an automated manner, add it as argument tonsenter
. It works a bit like chroot
, except that it works with containers instead of plain directories.
What about remote access?
If you need to enter a container from a remote host, you have (at least) two ways to do it:
- SSH into the Docker host, and use
nsenter
; - SSH into the Docker host, where a special key with force a specific command (namely,
nsenter
).
The first solution is pretty easy, but it requires root access to the Docker host (which is not great from a security point of view). The second solution uses the command=
pattern in SSH’s authorized_keys
file. You are probably familiar with “classic” authorized_keys
files, which look like this:
ssh-rsa AAAAB3N…QOID== jpetazzo@tarrasque
(Of course, a real key is much longer, and typically spans multiple lines.) You can also force a specific command. If you want to be able to check the available memory on your system from a remote host, using SSH keys, but you don’t want to give full shell access, you can put this in the authorized_keys
file:
command="free" ssh-rsa AAAAB3N…QOID== jpetazzo@tarrasque
Now, when that specific key connects, instead of getting a shell, it will execute the free
command. It won’t be able to do anything else. (Technically, you probably want to add no-port-forwarding
; check the manpageauthorized_keys(5)
for more information.) The crux of this mechanism is to split responsibilities. Alice puts services within containers; she doesn’t deal with remote access, logging, and so on. Betty will add the SSH layer, to be used only in exceptional circumstances (to debug weird issues). Charlotte will take care of logging. And so on.
Wrapping up
Is it really Wrong (uppercase W) to run the SSH server in a container? Let’s be honest, it’s not that bad. It’s even super convenient when you don’t have access to the Docker host, but still need to get a shell within the container. But we saw here that there are many ways to not run an SSH server in a container, and still get all the features we want, with a much cleaner architecture. Docker allows you to use whatever workflow is best for you. But before jumping on the “my container is really a small VPS” bandwagon, be aware that there are other solutions, so you can make an informed decision!