在 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
大部分发行版的nsenter
在util-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 驱动
如果你无法编译nsenter
或nsinit
,首先停掉docker daemon 服务,编辑服务启动文件(/etc/default/docker
)的DOCKER_OPTS
项,添加-e lxc
,重启docker daemon。好了,现在你又能重新使用lxc-attach
进入特定的容器了。
docker exec
升级你的docker到1.3版,然后执行
docker exec -it CONTAINNER_NAME bash
啊哈,还有比这个更简单的吗?更多细节