答案较晚,但可能对某人有帮助
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特有的行为,例如掩盖输入或为输出着色。