If you run applications in containers, you've probably needed a way to enter the container to debug something. Sure you could run sshd in your container, but its really not necessary. The same thing can be accomplished using a little program called nsenter.
nsenter can be used to enter both Docker containers and systemd-nspawn containers. In this situation, we're going to be looking at a container running with systemd-nspawn.
Start a container
To make things easier, we're going to pull the "vanilla" Fedora 21 Docker container and export its filesystem so we can run it with systemd-nspawn.
docker pull fedora:21 create a directory to dump everything into mkdir fedora21 docker export "$(docker create --name fedora21 fedora:21 true)" | tar -x -C fedora21 clean up Docker's mess docker rm fedora21
Now we can actually boot the machine. One thing to note here for those that are unfamiliar, is that when you boot the machine it's pretty much the same as turning on a physical machine; you'll see systemd start up and it'll show a command prompt. The act of using nsenter will be in a different shell/terminal/screen/whatever than the running machine.
> sudo systemd-nspawn --directory fedora21 --machine fedora-container --boot > machinectl list MACHINE CONTAINER SERVICE fedora-container container nspawn 1 machines listed.
Now that we have a machine running, we need to find the PID for systemd running in the container. We can do that using
> machinectl status fedora-container fedora-container Since: Thu 2015-04-09 23:44:35 UTC; 5min ago Leader: 7943 (systemd) Service: nspawn; class containerRoot: /home/core/fedora21 Address: 10.0.0.0OS: Fedora 21 (Twenty One) Unit: machine-fedora\x2dcontainer.scope ├─7943 /usr/lib/systemd/systemd └─system.slice ├─dbus.service │ └─7988 /bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation ├─systemd-journald.service │ └─7964 /usr/lib/systemd/systemd-journald ├─systemd-logind.service │ └─7987 /usr/lib/systemd/systemd-logind └─console-getty.service └─7992 /sbin/agetty --noclear --keep-baud console 115200 38400 9600 vt102
The PID we want is the one specified under "Leader", so
nsenter into the container
Based on the man page, nsenter:
Enters the namespaces of one or more other processes and then executes the specified program
In this case, that is systemd inside of the container we are running. The goal here is to nsenter into the container and get a simple bash shell running so that we can run commands as if we logged into it.
> sudo nsenter --target 7943 --mount --uts --ipc --net
That's it! If you run something like
whoami you'll see that you are in the container as the root user. You can now do everything you normally could if we logged in from the main login prompt or ssh'd into the machine.
When you're done, simply
control + d to logout. To terminate the container, you can use
sudo machinectl terminate fedora-container