首页 > 解决方案 > 从主机控制台分离容器

问题描述

我正在使用 python docker 包创建一个带有 Ubuntu:16.04 映像的 docker 容器。我将 tty 作为 True 并作为 True 分离到 client.containers.run() 函数。容器以 /sbin/init 进程开始。容器创建成功。但问题是,我的主机上的登录提示被我的主机控制台上的容器登录提示所取代。结果,我无法在控制台上登录机器。与机器的 SSH 连接工作正常。

即使我在将 SSH 连接到机器后运行我的 python 脚本也会发生这种情况。我尝试了不同的选项,例如将 tty 设置为 False,将 stdout 设置为 False,将容器中的环境变量 TERM 设置为 xterm,但没有任何帮助。

如果有人可以为这个问题提出解决方案,那就太好了。

我的脚本很简单:

import docker
client = docker.from_env()

container = client.containers.run('ubuntu:16.04', '/sbin/init', privileged=True,
       detach=True, tty=True, stdin_open=True, stdout=False, stderr=False,
       environment=['TERM=xterm'])

我没有使用任何 dockerfile。

我已经能够弄清楚当我以特权模式启动容器时会发生这个问题。如果我这样做,/sbin/init 进程会启动 /sbin/agetty 进程,这会导致 /dev/tty 附加到容器。我需要找到一种方法来启动 /sbin/init 以使其不会创建 /sbin/agetty 进程。

标签: docker

解决方案


/sbin/init在 Ubuntu 中是一个名为systemd的服务。如果您查看链接的页面,它会做很多事情——配置各种内核参数、挂载文件系统、配置网络、启动getty进程......其中许多事情需要更改主机全局设置,如果您启动容器--privileged你允许 systemd 这样做。

我会就这个命令给出两个关键建议:

不要在 Docker 中运行 systemd。 如果你真的需要一个多进程的 init 系统,supervisord很流行,但更喜欢单进程容器。如果您知道您需要一些init (8)(进程 ID 1 有一些职责),那么tini是另一个流行的选项。

不要直接运行裸 Linux 发行版映像。 无论您尝试运行什么软件,几乎可以肯定它不在一个alpineubuntu图像中。 构建一个包含您需要的软件的自定义镜像并运行;你应该正确设置它CMD,这样你就可以docker run在没有任何手动设置的情况下获得图像。

还要记住,运行任何 Docker 命令的能力意味着对主机的不受限制的根级别访问。您在这里看到了一些--privileged容器正在接管主机控制台的情况;它也非常容易阅读和编辑像主机/etc/shadow/etc/sudoers. 您显示的脚本类型在技术上没有任何问题,但您需要非常小心标准的安全问题。


推荐阅读