如何进入已经使用新 TTY 运行的 Docker 容器

Posted

技术标签:

【中文标题】如何进入已经使用新 TTY 运行的 Docker 容器【英文标题】:How to enter in a Docker container already running with a new TTY 【发布时间】:2014-01-22 19:37:09 【问题描述】:

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

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

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

【问题讨论】:

你试过docker attach [conainer-id] 吗? @shabbychef 除非 docker attach 已更改,否则 attach 命令附加到正在运行的 tty,而不是新的,因此问题标题是“...with new TTY”。这就是为什么下面的答案不使用附加命令的原因。 从 1.3 开始,有一种更简单的方法,如 this answer 所述 【参考方案1】:

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

docker exec -it [container-id] bash

注意:这假设bash 已安装在您的容器上。您可以运行 sh 或容器上安装的任何交互式 shell。

【讨论】:

我已将其更改为正确答案(来自我自己的),因为这种新方法在提出问题时并不存在,是目前最好的 IMO 方法。 但是请注意exec 不能作为普通终端。例如,您不能在容器内更改用户。 @Pithikos:我可以使用 exec 运行 shell,然后使用 su someuser 更改用户。运行 Docker 1.4.1 请注意阅读此讨论的任何人。我敢肯定docker exec -it 最终会提供一个功能齐全的伪 tty,但是目前(Docker 版本 1.9.1)还有一些不足:github.com/docker/docker/issues/8755 如果你得到错误 'exec: "bash": executable file not found in $PATH' 你可以试试这个:docker exec -it [container-id] /bin/sh【参考方案2】:

您应该使用 Jérôme Petazzoni 的名为“nsenter”的工具进入容器,而不使用 SSH。见:https://github.com/jpetazzo/nsenter

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

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

【讨论】:

这是正确的方法。见blog。 在 docker 1.3 中,有一个新命令 docker exec。这允许您输入正在运行的 docker:docker exec -it <container-id> bash(请参阅下面的答案) docker-enter 还存在吗?它给了我command not found【参考方案3】:

更新

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

这都是因为……

...它 [docker 0.9] 包含一个新的“引擎驱动程序”抽象,使使用成为可能 LXC 以外的其他 API 来启动容器。它还提供了一个新的 基于新 API 库 (libcontainer) 的引擎驱动程序 在不使用 LXC 工具的情况下处理控制组。主要问题是 如果您依靠 lxc-attach 对您的 容器,就像在容器内启动一个外壳,它是 对开发环境非常有用...

source

请注意,这将阻止新的host only networking optional feature of docker 0.11“工作”,您只会看到环回接口。 bug report


原来a different question的解决方案也是这个解决方案:

...您可以使用 docker ps -notrunc 获取完整的 lxc 容器 ID 和 然后使用 lxc-attach -n <container_id> 在该容器中运行 bash 作为 根。

更新:您很快将需要使用 ps --no-trunc 而不是已弃用的 ps -notrunc

查找完整的容器 ID

输入 lxc attach 命令。

顶部显示了运行 docker 启动的我的 apache 进程。

【讨论】:

那么,仅使用 Docker 是无法做到这一点的,对吧?我个人不喜欢自己混入 LXC。 有没有办法用 lxc-attach 运行命令来启动 bash?谢谢!! @qkrijger 据我所知这是正确的。为什么担心“混合”LXC?你知道 docker 是建立在 LXC 之上的吧? @joselo 我不明白你的问题,但我建议你创建一个更详细的新帖子?启动 docker 进程的方法有很多,例如使用 bash 或作为守护进程使用 -d 等。 @programster 是的,我意识到 :) 尽管如此,直接将 LXC 与 Docker 结合使用感觉就像是在黑客攻击。有趣,但不是真正可维护的。一般来说,应该在自己选择工作的抽象层中编码。如果你真的需要 LXC 本身,可能是时候在 Docker 上提出拉取请求了:)【参考方案4】:

第一步获取容器id:

docker ps

这会告诉你类似的东西

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

1170fe9e9460 localhost:5000/python:env-7e847468c4d73a0f35e9c5164046ad88 "./run_notebook.sh" 26 秒前 Up 25 seconds 0.0.0.0:8989->9999/tcp SLURM_TASK-303337_0

1170fe9e9460 是本例中的容器 ID。

第二,进入docker:

docker exec -it [container_id] bash

所以在上述情况下: docker exec -it 1170fe9e9460 bash

【讨论】:

【参考方案5】:

在容器中运行 tmux/GNU Screen 怎么样? 使用简单的方法似乎可以更顺畅地访问任意数量的 vty:

$ docker attach container id

【讨论】:

如果你知道你想要访问一个容器(例如调试它),这是一个不错的解决方案,但这不会帮助 OP 声明他们想要查看现有的容器。 我对这个答案的问题是人们已经询问过使用docker attach,我指出:...the attach command attaches to the running tty, not a new one, hence the question title is "...with new TTY" 好吧,如果容器已经在运行,这个解决方案对你没有帮助,但如果你以前注意让多路复用器运行,你就不需要额外的 tty... 事实上因为我开始使用 tmux,我使用一个 tty,并且只使用一个来完成我需要的一切,因为一旦进入 tmux,我就可以生成任意数量的 vty。【参考方案6】:
docker exec -ti 'CONTAINER_NAME' sh

or

docker exec -ti 'CONTAINER_ID' sh

【讨论】:

【参考方案7】:

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 很好,我不必像使用lxc-attach -n 代码库足够短,可以快速扫描整个代码库以查找任何恶意内容。 我在 gentoo 上以 app-emulation/docker-enter 的形式在 github.com/steveeJ/personal-portage-overlay 上提供了一个 ebuild。 我在programster.blogspot.co.uk/2014/01/…为 ubuntu 用户添加了一个教程/脚本自动执行此操作【参考方案8】:
docker exec -t -i container_name /bin/bash

将带您进入容器控制台。

【讨论】:

我遇到了这个问题,因为我遇到了同样的问题。在我修改之前,看起来相似的答案对我不起作用。不过我可以删除它。【参考方案9】:

“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

【讨论】:

【参考方案10】:

我在作为守护进程运行的 microsoft/iis 上启动了 powershell 使用

docker exec -it <nameOfContainer> powershell

【讨论】:

看起来好像问题是关于基于 linux 的容器。仅当您拥有基于 Windows 的容器或安装了 .NET Core 版本的 PowerShell 时,此答案才可能有效,例如PowerShell 6 或更高版本。【参考方案11】:

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。如果您使用的是 mintty,请尝试在命令前加上 'winpty'"

第五步:运行命令“$winpty docker exec -it container id sh

伏拉!!你现在在终端里面。

【讨论】:

以上是关于如何进入已经使用新 TTY 运行的 Docker 容器的主要内容,如果未能解决你的问题,请参考以下文章

Docker之基础指令

使用 grunt-shell 调用调用 docker run 的脚本时如何解决“输入设备不是 TTY”?

用docker的composer安装php依赖包

如何在容器中运行docker命令

docker 错误:输入设备不是 TTY。如果您使用的是 mintty,请尝试在命令前加上“winpty”[重复]

如何从亚马逊上正在运行的容器创建新的 docker 镜像?