是否可以在正在运行的容器中启动Shell会话(不使用ssh)


341

我天真地希望此命令在正在运行的容器中运行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登录吗?


1
docker run CONTAINER计划在1.0
kolypto

7
从docker 1.3开始,您应该按照此答案的说明进行操作
Thomasleveil 2014年

1
刚刚docker attach container_name
maxbellec

1
如今看来,第二个答案要比认可的答案好得多-您能重新考虑更改接受的答案吗?
jsbueno 2015年

Answers:


285

编辑:现在您可以使用 docker exec -it "id of running container" bashdoc

以前,此问题的答案是:

如果确实需要并且您处于调试环境中,则可以执行以下操作: sudo lxc-attach -n <ID> 请注意,ID必须为完整的ID(docker ps -notrunc)。

但是,我强烈建议不要这样做。

注意:-notrunc已弃用,--no-trunc很快将被替换。


1
你为什么反对呢?
Max L.

7
我建议不要这样做,因为1)它需要一个非常新的内核,2)您正在docker之外做事,因此您将无法对其进行跟踪(日志,附加等)。另外,Docker现在可能会使用lxc,但没有任何保证,它将永远使用。
creack

1
尝试更新至0.7.6。Docker现在仍在使用lxc,lxc-attach应该可以正常工作。我只是仔细检查了一下,它对我有用。(请注意,它不适用于3.8之前的内核)。
creack

2
从0.9开始,默认情况下Docker不再与LXC一起运行。您必须使用docker -d -e lxc
kevzettler 2014年

2
Max L.,您的用例可以通过数据量解决。未测试实施例:1)运行容器中的数据量的nginx日志:docker run -v /var/log/nginx -name somename imagename command; 2)运行另一个容器,以查看该数据体积含量:docker run -volumes-from somename -i -t busybox /bin/sh
ciastek 2014年

615

对于docker 1.3,有一个新命令docker exec。这使您可以输入正在运行的泊坞窗:

docker exec -it "id of running container" bash

2
这对我来说很棒。对docker run很有帮助。
oraserrata 2014年

如果我在执行一个正在运行的容器时执行更改并希望在线反映更改怎么办?最佳做法是什么?
mediaroot 2015年

很有用。谢谢
luongnv89

用于docker ps获取正在运行的实例的ID
Muon

注意:该容器可能没有bash(»exec:“ bash”:找不到可执行文件«)。用docker inspect <image>看什么shell可用。例如运行docker exec -it <container id> /bin/sh
pixelbrackets

14

做就是了

docker attach container_name

如注释中所述,要在不停止的情况下与容器分离,请键入Ctrlpthen Ctrlq


5
谢谢!!它有帮助。关于实际问题,我想补充一点。使用调试我们的容器后,docker attach container_name使用ctrl pctrl q代替exitexit命令停止容器,将容器停在原处ctrlpctrl q仅使该容器分离并保持其运行
phoenix 2014年

10

由于情况正在发生变化,目前建议使用访问运行中容器的方法 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ômePetazzoni的博客条目中找到关于该主题的很好的解释:为什么不需要在Docker 容器中运行sshd


不幸的是,使用这种方法会弄乱环境变量(如果您想检查链接创建的变量)。我建议这样做source /proc/*/environ
Tomas Tomecek 2014年

8

您无法运行的第一件事

docker run "existing container" command

因为此命令需要图像而不是容器,并且总会产生新的容器(所以不是您要查看的容器)

我同意以下事实:在docker方面,我们应该以不同的方式进行思考(因此,您应该找到无需登录到容器的方式),但是我仍然觉得它很有用,这就是我的工作方式周围。

我通过主管以DEAMON模式运行命令。

然后执行我所谓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进入一个外壳中,使您可以像正常系统一样窥视一下。

还请注意,该系统不如没有外壳的容器安全,因此请采取所有必要步骤来固定容器。


5

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

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

nsinit可以这样做:“ nsinit提供了一种方便的方法来访问正在运行的容器的命名空间中的shell”,但是看起来很难运行。 https://gist.github.com/ubergarm/ed42ebbea293350c30a6


docker exec登陆Docker 1.3,因此现在可以在运行中的容器中创建并加入新的Shell会话
Foz,2014年


1

实际上,有一种在容器中放置外壳的方法。

假设你的 /root/run.sh启动流程,流程管理器(主管)或其他。

/root/runme.sh使用一些gnu屏幕技巧创建:

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

现在,在选项卡0中有守护程序,在选项卡1中有交互外壳。 docker attach中创建以便随时查看容器内部的情况。

另一个建议是使用所有必要的工具(包括此屏幕技巧)在生产映像的顶部创建“开发包”映像。


1

这是我的解决方案

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

构建映像后,您可以使用exec和attach两个选项:

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

泊坞窗运行--name $ CONTAINER_NAME -dt $ IMAGE_NAME

然后

docker exec -it $ CONTAINER_NAME / bin / bash

和使用

CTRL + D分离

  1. 附带,运行:

泊坞窗运行--name $ CONTAINER_NAME -dit $ IMAGE_NAME

然后

码头工人附上$ CONTAINER_NAME

和使用

CTRL + P和CTRL + Q分开

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


1

有两种方法。

带附件

$ sudo docker attach 665b4a1e17b6 #by ID

与执行

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


0

运行容器时,这很有用。您不需要引用container_id。

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


0

首先,通过以下方式获取所需容器的容器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

现在复制此容器标识并运行以下命令:

docker exec -it container_id sh

docker exec -it 3ac548b6b315 sh


-2

在开发容器时,也许您像我一样误导了关于VM的思考。我的建议:尽量不要。

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

通常,您只是“运行”该过程,因此,如果您想修改配置或阅读日志,只需创建一个新容器,并确保通过共享目录并写入stdout来在其中写入日志(这样docker日志就可以了)或类似的东西。

出于调试目的,您可能要先启动外壳程序,然后启动代码,然后按CTRL-p + CTRL-q使外壳完好无损。这样,您可以使用以下方法重新连接:

docker attach <container_id>

如果您要调试容器是因为它正在做您没想到的事情,请尝试对其进行调试:https : //serverfault.com/questions/596994/how-can-i-debug-a-docker-container -初始化


这是完全错误的。能够内省运行您的应用程序的LXC名称空间并不是“非常特殊的情况”,对于任何开发人员来说,这都是常见的/日常的活动。
sleepycal 2014年

@sleepycal“任何开发人员”听起来有点偏颇。无论如何,我都会使用过程的自省,所以同样的事情也适用于容器。这就是调试背后的想法。您将调试器附加到该进程(可能具有CLI)。认为您“已”登录到容器听起来仍然对我产生误解。
estani 2014年

-4

不可以。supervisord如果需要,可以使用类似的方法来获取ssh服务器。虽然,我绝对质疑这一需求。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.