是否可以在运行的容器中启动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服务器并通过SSH登录吗?

252153 次浏览

不。这是不可能的。如果需要的话,使用类似supervisord的东西来获取ssh服务器。不过,我对这种必要性表示怀疑。

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

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

如果你真的必须并且你在调试环境中,你可以这样做:sudo lxc-attach -n <ID> 注意,id必须是完整的id (docker ps -notrunc)

然而,我强烈建议不要这样做。

注意:-notrunc已弃用,它将很快被--no-trunc取代。

如果目标是检查应用程序的日志,这篇文章展示了启动tomcat并作为CMD的一部分跟踪日志。tomcat日志可以通过'docker logs containerid'在主机上获取。

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

首先,你不能跑

docker run "existing container" command

因为这个命令期望的是图像而不是容器,它无论如何都会生成一个新容器(所以不是你想要查看的那个)

我同意这样一个事实,使用docker我们应该迫使自己以不同的方式思考(所以你应该找到方法,这样你就不需要登录到容器上),但我仍然觉得它很有用,这就是我如何围绕它工作的。

我在DEAMON模式下通过supervisor执行命令。

然后执行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,让你可以像正常的系统一样窥视周围

请同时考虑到这个系统不如没有外壳的容器安全,所以请采取所有必要的步骤来保护您的容器。

只做

docker attach container_name

正如注释中提到的,要在不停止容器的情况下从容器中分离,输入__abc0__abc1,然后输入Ctrl

也许在开发容器时,您也像我一样被误导,从vm的角度进行思考。我的建议是:尽量不要。

容器就像任何其他过程一样。实际上,出于调试目的,您可能想要“附加”到它们(考虑/proc//env或strace -p),但这是非常特殊的情况。

通常你只是“运行”进程,所以如果你想修改配置或读取日志,只需创建一个新容器,并确保通过共享目录、写入stdout(这样docker日志就可以工作了)或类似的东西在容器外面写入日志。

出于调试目的,您可能希望先启动一个shell,然后启动代码,然后按CTRL-p + CTRL-q以保持shell不变。这样你就可以使用:

docker attach <container_id>

如果你想调试容器,因为它正在做一些你不希望它做的事情,尝试调试它:https://serverfault.com/questions/596994/how-can-i-debug-a-docker-container-initialization

实际上有一种方法可以让容器中有一个外壳。

假设你的/root/run.sh启动了进程、进程管理器(监督器)或任何东西。

使用一些gnu屏幕技巧创建/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'

现在,在tab 0中有守护进程,在tab 1中有交互式shell。docker attach来查看容器内发生了什么。

另一个建议是使用所有必要的工具在产品映像之上创建一个“开发包”映像,包括这个屏幕技巧。

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

你可以找到关于github库的更多信息。但通常你可以这样使用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ôme Petazzoni的博客上找到: 为什么不需要在docker容器中运行sshd < / p >

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

它实现了即将到来的docker exec <container_id> <command>实用程序。当它可用时,应该可以在运行的容器中启动和停止ssh服务。

还有nsinit来做这个:nsinit提供了一种方便的方法来访问正在运行的容器命名空间中的shell。,但它看起来很难运行。 https://gist.github.com/ubergarm/ed42ebbea293350c30a6 < / p >

在docker 1.3中,有一个新的命令docker exec。这允许你输入一个正在运行的docker:

docker exec -it "id of running container" bash

这是我的解决方案

在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

在映像构建之后,你有两个选项使用execattach:

  1. 使用exec(首选)运行:

    docker run --name $CONTAINER_NAME -dt $IMAGE_NAME
    

    然后

    docker exec -it $CONTAINER_NAME /bin/bash
    

    并使用CTRL + D分离

  2. 使用附加和运行:

    docker run --name $CONTAINER_NAME -dit $IMAGE_NAME
    

    然后

    docker attach $CONTAINER_NAME
    

    并使用CTRL + PCTRL + 分离

    请注意:选项之间的区别在于参数-i

有两种方法。

与连接

$ sudo docker attach 665b4a1e17b6 #by ID

与执行

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

在运行容器时,分配名称是很有用的。您不需要引用container_id。

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

你可以使用

docker exec -it <container_name> bash

首先,通过获取所需容器的容器id

docker ps

你会得到这样的结果:

CONTAINER ID        IMAGE                  COMMAND             CREATED             STATUS                          PORTS                    NAMES
3ac548b6b315        frontend_react-web     "npm run start"     48 seconds ago      Up 47 seconds                   0.0.0.0:3000->3000/tcp   frontend_react-web_1


现在复制这个容器id并运行以下命令:

docker exec -it container_id sh


docker exec -it 3ac548b6b315 sh