Back to home

在 Docker 容器中如何绑定一个新的命令行

原文:http://jpetazzo.github.io/2014/03/23/lxc-attach-nsinit-nsenter-docker-0-9/ 添加 docker exec 使用部分

问题描述

Docker 0.9 之前,容器使用的是 lxc 驱动。从这个版本开始,Docker 通过自行实现了一个容器管理组件libcontainer进行管理。

通常在开发阶段我们需要对执行在容器中的应用进行调试,除了 docker log 等方式查看,有时我们会在一个容器中启动一个SSHD以保证我们能够登陆进去。这是一种方案,但是绝对称不上简便。

解决

在 0.9 之前,我们可以使用 lxc-attach 进入一个容器进行管理。lxc-attach 通过 lxc-start 监听的socket连接(默认在 /var/lib/lxc/<container_name>/command 中)等到容器的PID,然后使用setns()系统调用将进程绑定到容器中。

在 0.9 之后,我们已经没有了原生的执行驱动,所以 lxc-attach 不再工作。但是我们还是有其他办法:

  • 使用 nsenter,一个Linux小工具,修改进入指定 namespaces
  • 使用 libcontainer 的内置工具 nsinit
  • 回滚到 LXC 驱动
  • 升级到 1.3,便有内置指令支持 docker exec

使用 nsenter

大部分发行版的nsenterutil-linux包中。首先你要拿到PID:

PID=$(docker inspect --format '{{.State.Pid}}' my_container_id)

现在进入它

nsenter --target $PID --mount --uts --ipc --net --pid

恭喜,你已经在容器中了。 Sebastien Han 已经提供了一些有用的使用方式。

使用 nsinit

Michael Crosby 觉得这是最好进入容器的方式。安装 nsinit 需要GO环境:

go install github.com/dotcloud/docker/pkg/libcontainer/nsinit/nsinit

然后你需要进入容器的配置目录,在哪?在 /var/lib/docker/execdriver/native/<container_id>/ 中,你可以通过 docker ps 找到他们。

然后执行

nsinit exec bash

就是这么简单。快来看看演示

回滚到 LXC 驱动

如果你无法编译nsenternsinit,首先停掉docker daemon 服务,编辑服务启动文件(/etc/default/docker)的DOCKER_OPTS项,添加-e lxc,重启docker daemon。好了,现在你又能重新使用lxc-attach进入特定的容器了。

docker exec

升级你的docker到1.3版,然后执行

docker exec -it CONTAINNER_NAME bash

啊哈,还有比这个更简单的吗?更多细节

引用