答案较晚,但可能对某人有帮助
docker run/exec -i
会将容器内命令的STDIN连接到容器docker run/exec
本身的STDIN 。
所以
docker run -i alpine cat
给您空行等待输入。输入“ hello”,您将得到回声“ hello”。在发送CTRL + D之前,容器不会退出,因为主进程cat
正在等待来自无限流(即的终端输入)的输入docker run
。
- 另一方面,
echo "hello" | docker -i run alpine cat
将显示“ hello”并立即退出,因为会cat
注意到输入流已结束并自行终止。
如果您docker ps
在退出以上任一方法后尝试,则将找不到任何正在运行的容器。在这两种情况下,cat
其自身都已终止,因此docker已终止了该容器。
现在,对于“ -t”,它告诉docker内部的主要过程其输入是终端设备。
所以
docker run -t alpine cat
会给您空行,但是如果您尝试键入“ hello”,则不会得到任何回显。这是因为当cat
连接到端子输入时,此输入未连接到您的输入。您输入的“ hello”未达到的输入cat
。cat
正在等待永远不会到达的输入。
echo "hello" | docker run -t alpine cat
也会给您空行,并且不会在CTRL-D上退出容器,但是您不会收到回声“ hello”,因为您没有通过 -i
如果发送CTRL + C,则返回外壳,但是如果现在尝试docker ps
,则看到cat
容器仍在运行。这是因为cat
仍在等待从未关闭的输入流。如果未-t
与结合使用,我没有发现单独使用任何有用的用途-i
。
现在,为了-it
在一起。这告诉cat它的输入是端子,同时将此端子连接到其输入docker run
是端子。docker run/exec
在将自己的输入传递到之前,将确保它的输入实际上是tty cat
。这就是为什么input device is not a TTY
尝试时会得到a的echo "hello" | docker run -it alpine cat
原因,因为在这种情况下,其docker run
自身的输入是来自先前回显的管道,而不是docker run
执行终端
最后,-t
如果-i
要执行将输入连接到输入的技巧,您为什么需要通过cat
?这是因为命令是终端时,命令会以不同的方式对待输入。这也是最好的例子
docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -uroot -p
会提示您输入密码。如果您键入密码,则将字符打印出来。
docker run -i alpine sh
给你一个空行。如果键入类似的命令,ls
则会得到输出,但不会得到提示或彩色输出。
在后两种情况下,您之所以会得到这种行为,是因为mysql
他们并shell
没有将输入视为tty,因此没有使用tty特有的行为,例如掩盖输入或为输出着色。