Docker - 如何进入一个正在运行的容器

遇到这个需求是因为由于长时间登陆到SSH服务器没有活动,超时自动断线. 重新登陆SSH后丢失了容器的SHELL,需要重新进入容器.

搜刮了各种引擎后,主要有lxc-attach,nsenter, nsinit几种方式, 其中lxc-attach官方已经不建议使用,nsinit是官官方基于libcontainer开发的一个容器管理工具,需要安装Golang运行环境,稍微麻烦, 为了方便选用nsenter

Ubuntu 14.04util-linux包是2.20版本的, nsenter2.23中才有, 所以需要编译util-linux包的源码

nsenter

1
cd /tmp
wget https://www.kernel.org/pub/linux/utils/util-linux/v2.24/util-linux-2.24.tar.gz
tar zxf util-linux-2.24.tar.gz
cd util-linux-2.24
./configure --without-ncurses
make nsenter
cp nsenter /usr/local/bin

为了连接到容器,需要找出容器的第一个进程的PID:

首先查看一下容器的ID

1
root@localhost:~# docker ps --no-trunc
CONTAINER ID                                                       IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
27db60e7b9537954d62892eee64aa320f23923f5bee833f54d39fb3b9379f0c3   d9d3a87018ae        "/bin/bash"         About an hour ago   Up About an hour    0.0.0.0:8080->8080/tcp   evil_pare

其次, 找出容器第一个进程的PID

我们看到容器第一个进程的PID为27188,接下来就可以通过nsenter进入容器了

1
root@localhost:~# nsenter --target 27188 --mount --uts --ipc --net --pid

设置一下别名,减少输入

1
root@localhost:~# alias nsenter='nsenter --mount --uts --ipc --net --pid --target'

现在我们就可以这样输入了:

1
root@localhost:~# nsenter 27188

nsenter 的快捷方法

1
root@localhost:~# wget -O /usr/local/bin/docker-enter https://github.com/jpetazzo/nsenter/raw/master/docker-enter
root@localhost:~# chmod +x /usr/local/bin/docker-enter
root@localhost:~# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                                                                    NAMES
efb53d441c79        ffa21f762b09        "/bin/bash"         6 hours ago         Up 6 hours          0.0.0.0:3307->3306/tcp, 0.0.0.0:8080->8080/tcp, 0.0.0.0:9000->9000/tcp   sleepy_lalande
root@localhost:~# docker-enter efb53d441c79
root@efb53d441c79:~#

lxc-attach

Docker 0.9之后的lxc-attach方式已经被弃用,如需使用lxc-attach,要修改一个Docker的启动参数,编辑/etc/default/docker配置文件,设置选项DOCKER_OPTS="-e lxc"并重启Docker服务

1
# /etc/default/docker
DOCKER_OPTS="-e lxc"

重启 docker 服务

1
service docker restart

nsinit

参考资料

  1. https://blog.codecentric.de/en/2014/07/enter-docker-container/