docker - 从主机控制台分离容器
问题描述
我正在使用 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 进程。
解决方案
/sbin/init
在 Ubuntu 中是一个名为systemd的服务。如果您查看链接的页面,它会做很多事情——配置各种内核参数、挂载文件系统、配置网络、启动getty
进程......其中许多事情需要更改主机全局设置,如果您启动容器--privileged
你允许 systemd 这样做。
我会就这个命令给出两个关键建议:
不要在 Docker 中运行 systemd。 如果你真的需要一个多进程的 init 系统,supervisord很流行,但更喜欢单进程容器。如果您知道您需要一些init (8)(进程 ID 1 有一些职责),那么tini是另一个流行的选项。
不要直接运行裸 Linux 发行版映像。 无论您尝试运行什么软件,几乎可以肯定它不在一个alpine
或ubuntu
图像中。 构建一个包含您需要的软件的自定义镜像并运行它;你应该正确设置它CMD
,这样你就可以docker run
在没有任何手动设置的情况下获得图像。
还要记住,运行任何 Docker 命令的能力意味着对主机的不受限制的根级别访问。您在这里看到了一些--privileged
容器正在接管主机控制台的情况;它也非常容易阅读和编辑像主机/etc/shadow
和/etc/sudoers
. 您显示的脚本类型在技术上没有任何问题,但您需要非常小心标准的安全问题。
推荐阅读
- java - 如何使用使用 bpchar 的 h2 数据库执行单元测试?
- javascript - Javascript - 如何对多个 ajax 循环的结果求和
- python - 即使我使用了 super(),__init__() 方法也会被覆盖。为什么?
- python - Google pydrive 将文件上传到特定文件夹
- c++ - 如果一个用零填充整个 RAM 会发生什么
- html - 如何在 CSS/HTML 中的 em 和视口大小之间进行选择?
- sql - JPA - 我得到多行而不是 1
- excel - 在 for 循环的第一步后,Range 对象的偏移属性返回空?
- python - 如何排序列表,首先按项目的频率,然后按项目的值
- swift - 如何使用 YouTube API 查询修复 401 错误?