docker stdin 和 tty 标志如何在容器中工作?

Sen*_*ran 4 containers stdin tty docker

我经常使用这些命令行选项,-i以及-t在使用我想要与之交互的容器时。

  -i, --stdin=false: Pass stdin to the container
  -t, --tty=false: Stdin is a TTY
Run Code Online (Sandbox Code Playgroud)

这些如何使容器具有交互性?

Sha*_*k V 5

当您使用-i选项时,客户端(即docker命令)将自身附加到容器内命令的标准输入。如果使用-t选项,您还会将终端附加到命令。连接到终端时,某些程序的行为有所不同。


bash-3.2$ docker run -i ubuntu cat
Hey    <-- input from my stdin
Hey    --> output from cat
Hello  <-- input from my stdin
Hello  --> output from cat
Run Code Online (Sandbox Code Playgroud)

cat命令的标准输入连接到docker run命令的标准输入。


bash-3.2$ echo Hey | docker run -i ubuntu cat
Hey    --> output from cat
Run Code Online (Sandbox Code Playgroud)

在这里,command 的 stdincat连接到 stdin,而后者docker run又连接到 的 stdout echodocker run一旦标准输入断开就退出。


bash-3.2$ docker run -it ubuntu cat
Hey    <-- input from my stdin
Hey    --> output from cat
Run Code Online (Sandbox Code Playgroud)

的 stdincat连接到 tty 输入。该 tty 连接到 的 stdin docker run。stdindocker run也必须是 tty。

不确定如果 cat 的标准输入是 tty,它的行为是否会有所不同,但许多其他程序都会这样做。示例:某些命令在从 tty 获取密码输入时可能会隐藏输入。


bash-3.2$ echo Hey | docker run -it ubuntu cat
the input device is not a TTY
Run Code Online (Sandbox Code Playgroud)

docker run命令的标准输入不是 tty。因此它无法连接到连接到cat命令的标准输入的 tty。


bash-3.2$ docker run -t ubuntu cat
Hey    <-- input from my stdin. no output from cat
Run Code Online (Sandbox Code Playgroud)

cat命令的标准输入已连接到 tty,仅此而已。docker run命令的标准输入未连接到,cat因为-i未使用选项。因此,即使您在标准输入中输入任何内容,它也不会到达cat.


bash-3.2$ echo Hey | docker run -t ubuntu cat

Run Code Online (Sandbox Code Playgroud)

cat命令的标准输入已连接到 tty,仅此而已。的输出echo达不到cat.


这些如何使容器具有交互性?

客户端向 docker 守护进程发出API 调用/containers/{id}/attach然后,该 HTTP 连接被劫持,通过底层套接字传输stdinstdout、 和stderr(取决于选项)。客户端和服务器使用此套接字进行双向流传输。

根据是否启用 tty,流格式可能会有所不同。来自container_attach.go

// If the container is using a TTY, there is only a single stream (stdout), and
// data is copied directly from the container output stream, no extra
// multiplexing or headers.
//
// If the container is *not* using a TTY, streams for stdout and stderr are
// multiplexed.
// The format of the multiplexed stream is as follows:
//
//    [8]byte{STREAM_TYPE, 0, 0, 0, SIZE1, SIZE2, SIZE3, SIZE4}[]byte{OUTPUT}
//
// STREAM_TYPE can be 1 for stdout and 2 for stderr
//
// SIZE1, SIZE2, SIZE3, and SIZE4 are four bytes of uint32 encoded as big endian.
// This is the size of OUTPUT.
Run Code Online (Sandbox Code Playgroud)

在客户端,流中的数据被复制到它的标准输出上,并且它的标准输入被复制到流上