Software Engineer, builder of webapps

nsenter a systemd-nspawn container

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

> 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 7943.

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 machinectl terminate

sudo machinectl terminate fedora-container