For troubleshooting purposes, we sometimes need to enter the container or execute some commands with root privilege.
Sometimes, we simply cannot sudo or have the root password.
123
jenkins@jenkins:~$ sudo ls /etc/hosts
[sudo] password for jenkins:
Sorry, try again.
Modifying the Docker image to set root password (e.g., by editing Dockerfile and rebuild) is sometimes not an option,
such as when the Docker image is downloaded from another source and read-only.
Moreover, if the container is running in production, we don’t want to stop the container while troubleshooting some temporary issues.
nsenter approach
I found one way to enter a “live” container as root by using nsenter.
In summary, we find the process ID of the target container and provide it to nsenter as an argument.
In the case of a Kuberentes cluster, we need to find which Kubernetes slave the pod is running on and log into it to execute the following docker commands.
Finding running container ID and name
1234
[centos@kube-worker-1 ~]$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
943d6e5a3bb8 docker.registry.company.net/tdongsi/jenkins:2.23 "/usr/local/bin/tini 25 hours ago Up 25 hours k8s_jenkins.6e7c865_...
fadfc479f24e gcr.io/google_containers/pause:0.8.0 "/pause" 25 hours ago Up 25 hours k8s_POD.9243e30_...
Use docker inspect to find the process ID based on the container ID.
The Go template { {.State.Pid} } (NOTE: without space) is used to simplify the output to a single numerical Pid.
For later versions of Docker, the more direct way is to use docker exec with the container name shown in docker ps output (see next section).
However, note that docker exec might not work for earlier versions of Docker (tested with Docker 1.6) and nsenter must be used instead.
After entering the container as root, you might want to add the user into sudo group and save the modified Docker image.
Later versions of docker adds --user flag that allows us to specify which user that we should enter the container as.
First, we figure out which Kubernetes node is running a particular pod by using the command kubectl describe pod.
After ssh-ing into that Kubernetes node, we can find the corresponding container running in that pod with the command docker ps -a.
The following examples demonstrate entering a jenkins-slave container as root and jenkins user.
Entering container
12345678910111213141516171819
[root@dev-worker-2 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
10f031d08389 docker.registry.company.net/tdongsi/jenkins:jenkins-agent "jenkins-slave 9f22f2" 19 minutes ago Up 19 minutes k8s_slave.beb667bf_...
767915746e2c docker.registry.company.net/tdongsi/pause:2.0 "/pause" 19 minutes ago Up 19 minutes k8s_POD.abb8e705_...
[root@dev-worker-2 ~]# docker exec -it --user root 10f031d08389 /bin/sh
#
# ls
support workspace
# id
uid=0(root) gid=0(root) groups=0(root)
# exit
[root@dev-worker-2 ~]# docker exec -it --user jenkins 10f031d08389 /bin/sh
$ ls
support workspace
$ id
uid=25001(jenkins) gid=25001(jenkins) groups=25001(jenkins),992(docker)
$ exit
As mentioned, older versions of docker does not support --user flag and does not allow entering container as root.
In that case, use nsenter method presented in the previous section.
Unsupported operation on Docker 1.6
1234567891011121314
[root@kube-worker-1 ~]# docker exec -it --user root af9a884eb3f1 /bin/sh
flag provided but not defined: --user
See 'docker exec --help'.
[root@kube-worker-1 ~]# docker version
Client version: 1.6.2.el7
Client API version: 1.18
Go version (client): go1.4.2
Git commit (client): c3ca5bb/1.6.2
OS/Arch (client): linux/amd64
Server version: 1.6.2.el7
Server API version: 1.18
Go version (server): go1.4.2
Git commit (server): c3ca5bb/1.6.2
OS/Arch (server): linux/amd64