In previous articles [1 ,2 ,3 ] Lukas Pustina has given an introduction to system-level virtualization with Docker. In this article I discuss 4 options how to connect to a running Docker container and interact with it. All code examples are available on GitHub so you can try yourself.
nsenter
The nsenter tool is part of the util-linux package since version 2.23. It provides access to the namespace of another process. nsenter requires root privileges to work properly. Unfortunately, util-linux is still at version 2.20 in Ubuntu 14.04. To install the latest version (2.24) proceed as follows:
1cd /tmp 2curl https://www.kernel.org/pub/linux/utils/util-linux/v2.24/util-linux-2.24.tar.gz | tar -zxf- 3cd util-linux-2.24 4./configure --without-ncurses 5make nsenter 6cp nsenter /usr/local/bin
In order to connect to a container, you have to find out the PID of the first process in the container.
1docker inspect --format "{{ .State.Pid }}" <container-id>
With that PID you can connect to the container:
1nsenter --target $PID --mount --uts --ipc --net --pid
nsinit
Since version 0.9 Docker offers its own library for managing containers called libcontainer. The tool nsinit of the libcontainer allows the user direct access to the linux namespace and cgroup kernel features. Before you can install nsinit you have to install the Go runtime environment:
1apt-get install git golang-go 2 3mkdir -p $HOME/go-dev/bin 4mkdir -p $HOME/go-dev/src 5 6echo "export GOPATH=\$HOME/go-dev" >> ~/.profile 7echo "PATH=\$PATH:\$GOPATH/bin" >> ~/.profile 8 9source ~/.profile
In a second step, you install nsinit:
1mkdir -p $GOPATH/src/github.com/dotcloud 2cd $GOPATH/src/github.com/dotcloud 3 4git clone https://github.com/dotcloud/docker.git 5cd $GOPATH/src/github.com/dotcloud/docker 6 7/usr/bin/go get -v github.com/dotcloud/docker/vendor/src/github.com/docker/libcontainer/nsinit
nsinit reads the configuration data from the container directory located in /var/lib/docker/execdriver/native/. In order to use nsinit you have to change into that container directory. This requires root privileges because the directory /var/lib/docker is only readable for root. The container id can be determined with the docker ps command. Once you stepped into the directory you can connect to the container:
1nsinit exec /bin/bash
lxc(-attach)
Up to version 0.8.1 LXC was the base for Docker to manage containers and Docker still supports it. But since version 0.9.0 Docker uses libcontainer by default, cutting the dependency to LXC. Thus, you cannot use lxc-attach by default anymore.
If you still want to use lxc-attach you have to restart the Docker daemon with the -e lxc option. With this option Docker will use LXC under the hood again. The easiest way to do so, is to create the file /etc/default/docker (if it does not exist yet) and add the following line:
DOCKER_OPTS=”-e lxc”
Now you have to restart the Docker daemon. To connect to a container you need the full container id:
1docker ps --no-trunc
Now you can connect to the container. For this to work, root privileges are needed again:
1lxc-attach -n <container-id> -- /bin/bash
sshd
The three previous methods all require root privileges on the host system. To avoid that, accessing containers via SSH is a good alternative.
For that you need to build a base image supporting an SSH daemon. At this point we run into the problem that we can only execute one command with the Docker keywords CMD or ENTRYPOINT. If this were the sshd process we could not run any other process. A workaround is to create a script to start all necessary other processes or to use a process management tool like supervisord. There is excellent documentation on how to use supervisord on the Docker website. Once you have started a container with a sshd process, you can connect as usual with a ssh client.
Fazit
The sshd approach is probably the easiest one and the most users are accustomed to connect to a virtual machine via ssh. In addition, you also do not need root privileges in order to connect with a container. However, there are a lot of discussions [1 ,2 ] about whether a container should manage more than one process or not. In the end, you have one additional sshd process per container which is basically not the idea of process virtualization.
For the other three options, root privileges are required. Docker has used LXC to manage its containers up to version 0.8.1. For this reason, it was pretty easy to use lxc-attach. Since version 0.9.0 the Docker daemon must be started with the option -e lxc for still using LXC under the hood. But with this option set, Docker relies on LXC again which might vary across distributions or installations.
nsenter and nsinit are basically equivalent. The main difference between both tools is that nsinit will setup a new process in the container and nsenter will just enter the namespace. Jerome Petazzoni has described it very well in the Docker Blog .
More articles
fromAlexander Berresch
Your job at codecentric?
Jobs
Agile Developer und Consultant (w/d/m)
Alle Standorte
Gemeinsam bessere Projekte umsetzen.
Wir helfen deinem Unternehmen.
Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.
Hilf uns, noch besser zu werden.
Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.
Blog author
Alexander Berresch
Do you still have questions? Just send me a message.
Do you still have questions? Just send me a message.