这个选项到底有什么作用?我读了很多关于TTY的文章,但我还是很困惑。我没有使用-t,只使用-i,看起来程序需要用户输入而不使用-t就会抛出错误。为什么启用伪tty很重要?


当前回答

-it指示Docker分配一个伪tty连接到容器的stdin,在容器中创建一个交互式bash shell。

——interactive, -i false保持STDIN打开,即使没有附加

——tty, -t false分配一个伪tty

https://docs.docker.com/engine/reference/commandline/run/

其他回答

这里的大多数答案都是很好的概念性答案,但我发现他们遗漏了太多细节,让我坐在电脑前无法使用这些信息。Ahmed Gnomin的答案正在逐步成为程序化的,但让我们试着进一步推动它。

首先讲一点理论

TTY Demystified中的两幅图是关键:

我不能声称完全理解了这幅图,但这里的关系是当xterm(或ubuntu中的gnome-terminal;由上图中的一个“user process”气泡表示)打开,它启动一个bash(或任何默认shell),然后通过内核伪终端(PTY)主和从向它发送键盘输入:

Xterm -> PTMX (pty主)-> PTS (pty从)-> bash

第二张图表示在这个简短的bash会话中涉及的进程:

>>> cat
>>> ls | sort
...

关键信息是TTY和stdin、stdout、stderr行。这表明每个进程都与TTY(电传终端)相关联,并且它们的3个流(stdin, stdout, stderr)非常自然地与这个TTY相关联,除了管道或重定向的情况(注意管道ls | sort将ls的stdout与sort的stdin相关联)。

现在来测试一下这个理论

我们可以通过输入tty找到bash使用的伪终端:

>>> tty
/dev/pts/2

Bash因此与PTY从机2相关联(这可能意味着有另一个打开的终端,与主/从机对1相关联)。我们还可以获得Bash的stdin, stdout和stderr流:

>>> ls -l /proc/$$/fd
lrwx------ 1 samlaf samlaf 64 Jun 17 21:50 0 -> /dev/pts/2
lrwx------ 1 samlaf samlaf 64 Jun 17 21:50 1 -> /dev/pts/2
lrwx------ 1 samlaf samlaf 64 Jun 17 21:50 2 -> /dev/pts/2

实际上,它们都与bash的自然TTY slave相关。$$是一个bash变量,它返回bash的PID。我们同样可以通过使用ps和手动输入来找到它)。

最后用这个理论来回答最初的Docker问题

我们复制了上面的步骤,但这次是在docker容器中:

>>> docker run --rm -t ubuntu tty
/dev/pts/0
>>> docker run --rm ubuntu tty
not a tty

这是有意义的,因为-t分配了一个伪终端。

与-i相关的命令比较难以解释。

>>> docker run --rm ubuntu bash -c "ls -l /proc/\$\$/fd"
lrwx------ 1 root root 64 Jun 18 02:37 0 -> /dev/null
l-wx------ 1 root root 64 Jun 18 02:37 1 -> pipe:[9173789]
l-wx------ 1 root root 64 Jun 18 02:37 2 -> pipe:[9173790]
>>> docker run --rm -t ubuntu bash -c "ls -l /proc/\$\$/fd"
lrwx------ 1 root root 64 Jun 18 02:39 0 -> /dev/pts/0
lrwx------ 1 root root 64 Jun 18 02:39 1 -> /dev/pts/0
lrwx------ 1 root root 64 Jun 18 02:39 2 -> /dev/pts/0
>>> docker run --rm -it ubuntu bash -c "ls -l /proc/\$\$/fd"
lrwx------ 1 root root 64 Jun 18 02:39 0 -> /dev/pts/0
lrwx------ 1 root root 64 Jun 18 02:39 1 -> /dev/pts/0
lrwx------ 1 root root 64 Jun 18 02:39 2 -> /dev/pts/0

我还是不明白-我到底做了什么…我想要一些帮助! 我能找到的唯一一个有趣的命令,它似乎有区别:

>>> docker run --rm -a stdout -i ubuntu bash -c "ls -l /proc/\$\$/fd"
lr-x------ 1 root root 64 Jun 18 02:43 0 -> pipe:[9199896]
l-wx------ 1 root root 64 Jun 18 02:43 1 -> pipe:[9199897]
l-wx------ 1 root root 64 Jun 18 02:43 2 -> pipe:[9199898]
>>> docker run --rm -a stdout ubuntu bash -c "ls -l /proc/\$\$/fd"
lrwx------ 1 root root 64 Jun 18 02:43 0 -> /dev/null
l-wx------ 1 root root 64 Jun 18 02:43 1 -> pipe:[9197938]
l-wx------ 1 root root 64 Jun 18 02:43 2 -> pipe:[9197939]

Docker文档提到-a“附加到作为输入传递的流上”,但我还没有找到解释这意味着什么,以及它与-i选项有什么关系。

-it指示Docker分配一个伪tty连接到容器的stdin,在容器中创建一个交互式bash shell。

——interactive, -i false保持STDIN打开,即使没有附加

——tty, -t false分配一个伪tty

https://docs.docker.com/engine/reference/commandline/run/

Docker在线文档中提到它是“分配一个伪tty”,经常与-i一起使用:

https://docs.docker.com/reference/run/

我在jwilder/nginx-proxy docker容器的文档中看到它是这样使用的:

docker run -d -p 80:80 --name nginx -v /tmp/nginx:/etc/nginx/conf.d -t nginx

在这种情况下,它所做的是将输出发送到docker容器中的“虚拟”tty (Bash命令提示符/终端)。然后,您可以通过运行docker命令docker logs CONTAINER查看此输出,其中CONTAINER是容器ID的前两个字符。这个CONTAINER ID可以通过输入docker ps -a找到

我在下面的链接中看到了这个-t参数,它说

-t和-i标志分配一个伪tty并保持stdin打开 如果没有附上。这将允许您使用容器像 只要bash提示符在运行。

https://coreos.com/os/docs/latest/getting-started-with-docker.html

我对-t的了解如下:

docker exec -ti CONTAINER bash允许我在容器中“登录”。感觉像嘘嘘(其实不是)。

但问题是当我想恢复数据库时。

通常我dodocker exec -ti mysql.5.7 mysql -这里我在容器中执行mysql命令并获得一个交互式终端。

我添加了<dump。sql到前面的命令,以便我可以恢复一个db。但是它失败了,不能在非tty输入上启用tty模式。

删除-t会有所帮助。还是不明白为什么:

docker exec -i mysql.5.7 mysql < dump.sql

最后一个可行。希望这能帮助到人们。

在linux中,当你运行一个命令时,你需要一个终端(tty)来执行它。

因此,当你想要连接到docker(或在docker容器中运行命令)时,你必须提供选项-t,它考虑到docker容器中的终端。