是否有可能在正在运行的容器中启动一个shell会话(不使用ssh)

我天真地期待这个命令在运行的容器中运行一个bash shell:

docker run "id of running container" /bin/bash 

它看起来不可能,我得到的错误:

 2013/07/27 20:00:24 Internal server error: 404 trying to fetch remote history for 27d757283842 

所以,如果我想在运行容器中运行bash shell(例如,用于诊断目的)

我必须在其中运行SSH服务器并通过SSHlogin?

编辑:现在你可以使用docker exec -it "id of running container" bash ( doc )

以前,这个问题的答案是:

如果你真的必须和你在一个debugging环境中,你可以这样做: sudo lxc-attach -n <ID>请注意,id需要是完整的( docker ps -notrunc )。

不过,我强烈build议不要这样做。

注意: -notrunc已经被弃用了,它将很快被replace为--no-trunc

随着docker1.3,有一个新的命令docker exec 。 这可以让你input一个正在运行的docker:

 docker exec -it "id of running container" bash 

由于事情正在变化,目前推荐的访问正在运行的容器的方式是使用nsenter

你可以在这个github仓库find更多的信息。 但一般来说,你可以像这样使用nsenter:

 PID=$(docker inspect --format {{.State.Pid}} <container_name_or_ID>) nsenter --target $PID --mount --uts --ipc --net --pid 

或者你可以使用包装器docker-enter

 docker-enter <container_name_or_ID> 

关于这个主题的一个很好的解释可以在JérômePetazzoni的博客文章中find: 为什么你不需要在你的docker容器中运行sshd

做就是了

 docker attach container_name 

如注释中所述,要从容器中分离而不停止,请键入Ctrl + p然后Ctrl + q

首先你不能跑

 docker run "existing container" command 

因为这个命令是期待一个图像而不是一个容器 ,反正会导致一个新的容器被产生(所以不是你想要看的那个)

我同意这样一个事实,即docker工人应该以不同的方式思考(所以你应该想方设法让你不需要login容器),但是我仍然觉得它很有用,这就是我的工作方式周围。

我在DEAMON模式下通过pipe理员运行我的命令。

然后我执行我所说的docker_loop.sh内容几乎是这样的:

 #!/bin/bash /usr/bin/supervisord /usr/bin/supervisorctl while ( true ) do echo "Detach with Ctrl-p Ctrl-q. Dropping to shell" sleep 1 /bin/bash done 

它所做的就是允许你“附加”到容器上,并提供supervisorctl接口来停止/启动/重新启动并检查日志。 如果这还不够的话,你可以Ctrl+D然后你就可以进入一个shell,这样你就可以像一个普通的系统一样偷看。

请注意,这个系统不像没有shell的容器那么安全,所以要采取一切必要的步骤来保护你的容器。

请留意这个请求: https : //github.com/docker/docker/pull/7409

其中实现了即将发布的docker exec <container_id> <command>实用程序。 当这是可用的,应该可以例如启动和停止正在运行的容器内的ssh服务。

还有nsinit可以做到这一点: “nsinit提供了一种方便的方式来访问正在运行的容器名称空间内的一个shell” ,但是看起来很难运行。 https://gist.github.com/ubergarm/ed42ebbea293350c30a6

实际上有一种方法在容器中有一个壳。

假设你的/root/run.sh启动了进程,进程pipe理器(主pipe)或者其他任何东西。

用一些gnu-screen的技巧创build/root/runme.sh

 # Spawn a screen with two tabs screen -AdmS 'main' /root/run.sh screen -S 'main' -X screen bash -l screen -r 'main' 

现在,你有在标签0的守护进程,并在标签1中的交互式shell。 docker attach随时docker attach看看容器内发生了什么。

另一个build议是在生产图像顶部创build一个“开发包”图像,并使用所有必要的工具,包括这个屏幕技巧。

这是我的解决scheme

部分DOckerfile:

 ... RUN mkdir -p /opt ADD initd.sh /opt/ RUN chmod +x /opt/initd.sh ENTRYPOINT ["/opt/initd.sh"] 

部分“initd.sh”

 #!/bin/bash ... /etc/init.d/gearman-job-server start /etc/init.d/supervisor start #very important!!! /bin/bash 

图像build立后,你有两个选项使用exec和attach:

  1. 与exec(我使用),运行:

docker运行 – 名称$ CONTAINER_NAME -dt $ IMAGE_NAME

然后

docker执行程序-it $ CONTAINER_NAME / bin / bash

并使用

CTRL + D分离

  1. 附带,运行:

docker运行 – 名称$ CONTAINER_NAME – $ $ IMAGE_NAME

然后

docker工人附加$ CONTAINER_NAME

并使用

CTRL + P和CTRL + Q分离

选项之间的区别在参数-i中

有两种方法。

随附

 $ sudo docker attach 665b4a1e17b6 #by ID 

与执行

 $ sudo docker exec - -t 665b4a1e17b6 #by ID 

如果目标是检查应用程序的日志,这篇文章展示了启动tomcat和拖尾日志作为CMD的一部分。 tomcat日志在主机上使用'docker logs containerid'。

http://blog.trifork.com/2013/08/15/using-docker-to-efficiently-create-multiple-tomcat-instances/

运行容器时有用的分配名称。 你不需要参考container_id。

docker run --name container_name yourimage docker exec -it container_name bash

也许你在开发容器的时候,像我自己一样误导了VM。 我的build议:尽量不要。

容器就像其他过程一样。 确实,你可能想“附加”到他们的debugging目的(想到/ proc / env或strace -p),但这是一个非常特殊的情况。

通常你只是“运行”进程,所以如果你想修改configuration或读取日志,只需创build一个新的容器,并确保通过共享目录写入到stdout(所以docker日志工作)或类似的东西。

出于debugging的目的,你可能想要启动一个shell,然后是你的代码,然后按CTRL-P + CTRL-q使shell保持不变。 这样你可以重新使用:

 docker attach <container_id> 

如果你想debugging容器,因为它正在做一些你没有想到的事情,请尝试debugging它: https : //serverfault.com/questions/596994/how-can-i-debug-a-docker-container -初始化

不,这是不可能的。 如果需要的话,使用像supervisord这样的东西来获得一个SSH服务器。 虽然,我当然质疑需要。