如何输入已经以新的TTY运行的Docker容器


545

我有一个在前台运行Apache服务的容器。我希望能够从另一个外壳访问该容器,以便在其中“探查”并检查文件。目前,如果我连接到容器,则只能查看Apache守护程序,并且无法运行任何命令。

是否可以将另一个tty附加到正在运行的容器?可能,我可以利用Docker实际上只是包裹LXC容器这一事实吗?我已经尝试过了,sudo lxc-console -n [container-id] -t [1-4]但是看来只有一个tty可用,而那是一个运行apache守护程序的tty。也许有一种在构建过程中启用多个lxc控制台的方法?

如果可能的话,我宁愿使用openssh服务配置和构建容器。


7
你尝试了docker attach [conainer-id]吗?
shabbychef 2014年

13
@shabbychef除非docker attach已更改,否则attach命令将附加到正在运行的tty,而不是新的tty,因此问题标题为“ ... with new TTY”。这就是为什么下面的答案不使用attach命令的原因。
Programster

1
从1.3开始,有一个更简单的方法,如此答案所述
Thomasleveil 2014年

Answers:


1060

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

docker exec -it [container-id] bash

30
我已将其更改为正确的答案(来自我自己的答案),因为在提出问题时还没有出现这种新方法,这是目前IMO最好的方法。
Programster

3
但是请注意,exec它不能用作普通终端。例如,您一次不能在容器内更改用户。
2014年

3
@Pithikos:我可以使用exec运行shell,然后su someuser更改用户。运行Docker 1.4.1
lsh 2015年

2
注意阅读此讨论的任何人。我确定docker exec -it最终将提供一个功能齐全的伪tty,但目前(Docker版本1.9.1)存在一些缺陷:github.com/docker/docker/issues/8755
blong

18
如果收到错误“ exec:“ bash”:在$ PATH中找不到可执行文件,则可以尝试以下操作:docker exec -it [container-id] / bin / sh
Dai Kaixian

42

您应该使用JérômePetazzoni的名为“ nsenter”的工具来输入容器,而无需使用SSH。参见:https : //github.com/jpetazzo/nsenter

只需运行即可安装: docker run -v /usr/local/bin:/target jpetazzo/nsenter

然后使用命令docker-enter <container-id>进入容器。


这是正确的方法。见博客
Jesse Glick 2014年

5
在docker 1.3中,有一个新命令docker exec。这使您可以输入正在运行的泊坞窗:(docker exec -it <container-id> bash请参阅下面的答案)
Michael_Scharf 2014年

5
是否docker-enter仍然存在?它给了我command not found
Snowcrash

22

更新资料

从docker 0.9开始,要使以下步骤正常运行,现在必须在重启守护程序之前使用docker daemon启动选项将/etc/default/docker文件更新'-e lxc'为docker守护进程(我通过重启主机来完成此操作)。

更新到/ etc / default / docker文件

这是因为...

... [docker 0.9]包含新的“引擎驱动程序”抽象,以使可以使用LXC以外的其他API来启动容器。它还提供了一个基于新API库(libcontainer)的新引擎驱动程序,该驱动程序无需使用LXC工具即可处理控制组。主要问题是,如果您依靠lxc-attach对容器执行操作,例如在容器内部启动外壳,这对于开发环境非常有用...

资源

请注意,这将阻止docker 0.11的新的仅主机联网可选功能 “正常运行”,并且您只会看到回送接口。错误报告


事实证明,另一个问题的解决方案也是这个问题的解决方案:

...您可以使用docker ps -notrunc获取完整的lxc容器ID,然后lxc-attach -n <container_id>在该容器中以root 身份使用run bash。

更新:您很快将需要使用ps --no-trunc而不是ps -notrunc不推荐使用。

在此处输入图片说明 查找完整的容器ID

在此处输入图片说明 输入lxc attach命令。

在此处输入图片说明 顶部显示运行docker启动的我的Apache进程。


因此,仅靠Docker就无法做到这一点,对吗?我个人不希望自己混入LXC。
qkrijger 2014年

有什么方法可以通过lxc-attach运行命令来启动bash吗?谢谢!!
2014年

据我所知,@ qkrijger是正确的。为什么要担心“混合” LXC?您意识到docker是建立在LXC之上的吧?
Programster

@joselo我不明白您的问题,但是我建议您创建一个更详细的新帖子?有很多方法来启动一个泊坞窗过程中,如bash或与-d等守护进程
Programster

@programster是的,我意识到:)尽管如此,直接将LXC与Docker结合使用仍感觉像是被黑客入侵。很有趣,但并不是真正可维护的。通常,应该在选择使用的抽象层中进行编码。如果您真的需要LXC本身,那么可能是时候在Docker上进行拉取请求了:)
qkrijger 2014年

7

第一步骤,这样就集装箱ID:

docker ps

这将显示类似

容器ID图像命令创建的状态端口名称

1170fe9e9460 localhost:5000 / python:env-7e847468c4d73a0f35e9c5164046ad88“ ./run_notebook.sh” 26秒前向上25秒0.0.0.0:8989->9999/tcp SLURM_TASK-303337_0

1170fe9e9460 在这种情况下是容器ID。

其次,进入泊坞窗:

docker exec -it [container_id] bash

因此在上述情况下: docker exec -it 1170fe9e9460 bash


5

在容器中运行tmux / GNU Screen怎么办?似乎更简单的方法是通过一个简单的方法来访问任意数量的vty:

$ docker attach {container id}

如果您知道要访问一个容器(例如,对其进行调试),那么这是一个不错的解决方案,但是这对OP声明他们想查看现有容器的OP没有帮助。
卡·史派勒

1
我对这个答案的问题是,人们已经问过使用的问题docker attach,我指出:...the attach command attaches to the running tty, not a new one, hence the question title is "...with new TTY"
Programster

好吧,如果该容器已经在运行,那么该解决方案将无济于事,但是如果您以前照顾了多路复用器的运行,那么您将不需要任何其他ttys ...实际上,因为我开始使用tmux,所以我使用了一个tty而且只有一个人可以做我需要的一切,因为一旦进入tmux,我就可以生成任意数量的vty。
cig0 2014年

4

nsenter做到这一点。但是,我还需要以一种简单的方式输入一个容器,nsenter不足以满足我的需求。在某些情况下,这是错误的(黑屏加上-wd标志不起作用)。此外,我想以特定用户身份和特定目录登录。

我最终制作了自己的工具来输入容器。您可以在以下位置找到它:https : //github.com/Pithikos/docker-enter

它的用法就像

./docker-enter [-u <user>] [-d <directory>] <container ID>

刚刚尝试过,非常酷!在ubuntu上必须运行sudo apt-get build-essential -y gcc docker-enter.c -o docker-enter sudo ./docker-enter <short-container-id>很好,我不必像这样获取完整ID lxc-attach -n代码库足够短,可以快速扫描整个内容以查找是否有恶意。
Programster

我在github.com/steveeJ/personal-portage-overlay上的gentoo上提供了一个ebuild,作为app-emulation / docker -enter。
stefanjunker


2

“ nsinit”的方式是:

安装nsinit

git clone git@github.com:dotcloud/docker.git
cd docker
make shell

从容器内部:

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

从外面:

docker cp id_docker_container:/go/bin/nsinit /root/

用它

cd /var/lib/docker/execdriver/native/<container_id>/
nsinit exec bash

2
docker exec -t -i container_name /bin/bash

将带您进入容器控制台。


我遇到了这个问题,因为我遇到了同样的问题。在我修改之前,似乎相似的答案对我不起作用。我可以删除它。
丹斯坦(Danstan)

2
docker exec -ti 'CONTAINER_NAME' sh

or

docker exec -ti 'CONTAINER_ID' sh

1

我在使用守护程序运行的运行Microsoft / iis上启动了Powershell

docker exec -it <nameOfContainer> powershell

看起来问题似乎与基于Linux的容器有关。仅当您具有基于Windows的容器时,此答案才可能有效-或者-如果您安装了.NET Core版本的PowerShell,例如PowerShell 6或更高版本。
曼弗雷德

0

Windows 10上,我安装了docker。我在容器上运行Jnekins,遇到相同的错误消息。这是解决此问题的分步指南:

步骤1:打开gitbash并运行docker run -p 8080:8080 -p 50000:50000 jenkins。

步骤2:打开一个新终端。

步骤3:执行“ docker ps”以获取正在运行的容器的列表。复制容器ID。

步骤4:现在,如果您执行“ docker exec -it {container id} sh”或“ docker exec -it {container id} bash”,您将收到类似于“输入设备不是TTY的错误消息。使用薄荷,尝试在命令前加上“ winpty””

步骤5:运行命令“ $ winpty docker exec -it {container id} sh

哇!您现在位于终端机内。

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.