What exactly does this option do? I've been reading a lot on TTY and am still confused. I played around with not having the -t
and just -i
and it seems like programs that expect user input throw an error without the -t
. Why is it important for pseudo-TTY to be enabled?
这个选项到底是做什么的?我一直在读TTY,但我仍然感到困惑。我玩的没有-t和只是-i,似乎期望用户输入的程序在没有-t的情况下抛出错误。为什么启用伪TTY很重要?
5 个解决方案
#1
The "-t" option goes to how Unix/Linux handles terminal access. In the past, a terminal was a hardline connection, later a modem based connection. These had physical device drivers (they were real pieces of equipment). Once generalized networks came into use, a pseudo-terminal driver was developed. This is because it creates a separation between understanding what terminal capabilities can be used without the need to write it into your program directly (read man pages on stty
, curses
).
“-t”选项指向Unix / Linux如何处理终端访问。在过去,终端是强硬连接,后来是基于调制解调器的连接。这些都有物理设备驱动程序(它们是真正的设备)。一旦广义网络投入使用,就开发了伪终端驱动程序。这是因为它在理解可以使用哪些终端功能而无需直接将其写入程序之间创建了分离(阅读stty上的手册页,curses)。
So, with that as background, run a container with no options and by default you have a stdout stream (so docker run | <cmd>
works); run with "-i", and you get stdin stream added (so <cmd> | docker run -i
works); use "-t", usually in the combination "-it" and you have a terminal driver added, which if you are interacting with the process is likely what you want. It basically makes the container start look like a terminal connection session.
因此,以背景为例,运行一个没有选项的容器,默认情况下你有一个stdout流(所以docker run |
#2
The "-t" argument is NOT documented well, or mentioned by many people often, according to a Google search.
根据Google搜索,“-t”参数没有很好地记录,或者很多人经常提到。
It doesn't even show up when you display a list of (what should be) all docker client arguments by typing "docker" at the Bash prompt (with the latest version of 1.8.1).
当您通过在Bash提示符下键入“docker”(使用最新版本的1.8.1)显示所有docker客户端参数的列表时,它甚至不会显示。
In fact, if you try to get specific help about this argument by typing "docker -t --help" if gives this amazingly vague reply:
事实上,如果您尝试通过键入“docker -t --help”获得有关此参数的特定帮助,如果给出了这个非常模糊的回复:
"flag provided but not defined: -t"
“提供了标志但未定义:-t”
So, you can't be blamed for being confused about this argument!
所以,你不能因为对这个论点感到困惑而受到指责!
There is a mention in the Docker online documention which says it is to "Allocate a pseudo-tty" and is often used with -i:
在Docker在线文档中提到它是“分配伪tty”并且经常与-i一起使用:
https://docs.docker.com/reference/run/
I saw it used in the documentation for the terrific jwilder/nginx-proxy docker container in the following way:
我通过以下方式看到它在极好的jwilder / nginx-proxy docker容器的文档中使用:
docker run -d -p 80:80 --name nginx -v /tmp/nginx:/etc/nginx/conf.d -t nginx
In this case, what it does is send the output to the 'virtual' tty (Bash command prompt/terminal) within this docker container. You can then see this output by running the docker command "docker logs CONTAINER" where CONTAINER is the first couple of characters of this container's ID. This CONTAINER ID can be found by typing "docker ps -a"
在这种情况下,它所做的是将输出发送到此docker容器中的'virtual'tty(Bash命令提示符/终端)。然后,您可以通过运行docker命令“docker logs CONTAINER”来查看此输出,其中CONTAINER是此容器ID的前几个字符。输入“docker ps -a”即可找到此CONTAINER ID
I've seen this "-t" argument mentioned briefly in the following link, where it says, "The -t and -i flags allocate a pseudo-tty and keep stdin open even if not attached. This will allow you to use the container like a traditional VM as long as the bash prompt is running."
我在下面的链接中看到过这个“-t”参数,它说:“-t和-i标志分配一个伪tty并保持stdin打开,即使没有附加。这将允许你使用只要bash提示符正在运行,就像传统的VM一样容器。“
https://coreos.com/os/docs/latest/getting-started-with-docker.html
I hope this helps! I'm not sure why this isn't documented or used much. Maybe it's experimental and will be implemented as a documented feature in upcoming versions.
我希望这有帮助!我不确定为什么没有记录或使用太多。也许它是实验性的,并将在即将推出的版本中作为文档功能实现。
#3
Late answer, but might help someone
迟到的答案,但可能会帮助某人
docker run/exec -i
will connect the STDIN of the command inside the container to the STDIN of the docker run/exec
itself.
docker run / exec -i将容器内的命令的STDIN连接到docker run / exec本身的STDIN。
So
-
docker run -i alpine cat
gives you an empty line waiting for input. Type "hello" you get an echo "hello". The container will not exit until you send CTRL+D because the main processcat
is waiting for input from the infinite stream that is the terminal input of thedocker run
. - On the other hand
echo "hello" | docker -i run alpine cat
will print "hello" and exit immediately becausecat
notices that the input stream has ended and terminates itself.
docker run -i alpine cat给你一个空行等待输入。键入“你好”你得到一个回声“你好”。在发送CTRL + D之前容器不会退出,因为主进程cat正在等待来自无限流的输入,该无限流是docker run的终端输入。
另一方面回声“你好”| docker -i run alpine cat将打印“hello”并立即退出,因为cat注意到输入流已经结束并终止自身。
If you try docker ps
after you exit either of the above, you will not find any running containers. In both cases, cat
itself has terminated, thus docker has terminated the container.
如果在退出上述任何一个之后尝试使用docker ps,则无法找到任何正在运行的容器。在这两种情况下,cat本身都已终止,因此docker已终止容器。
Now for "-t", this tells the main process inside docker that its input is a terminal device.
现在为“-t”,这告诉docker内部的主进程它的输入是终端设备。
So
-
docker run -t alpine cat
will give you an empty line, but if you try to type "hello", you will not get any echo. This is because whilecat
is connected to a terminal input, this input is not connected to your input. The "hello" that you typed did not reach the input ofcat
.cat
is waiting for input that never arrives. -
echo "hello" | docker run -t alpine cat
will also give you an empty line and will not exit the container on CTRL-D but you will not get an echo "hello" because you didn't pass-i
docker run -t alpine cat会给你一个空行,但是如果你试着键入“hello”,你就不会得到任何回音。这是因为当cat连接到终端输入时,此输入未连接到您的输入。你输入的“hello”没有达到cat的输入。猫正等待从未到过的输入。
echo“你好”| docker run -t alpine cat也会给你一个空行并且不会在CTRL-D上退出容器,但你不会得到一个echo“hello”,因为你没有通过-i
If you send CTRL+C, you get your shell back, but if you try docker ps
now, you see the cat
container still running. This is because cat
is still waiting on an input stream that was never closed. I have not found any useful use for the -t
alone without being combined with -i
.
如果你发送CTRL + C,你会得到你的shell,但如果你现在尝试使用docker ps,你会看到cat容器仍在运行。这是因为cat仍在等待从未关闭的输入流。我没有找到任何有用的-t单独使用而不与-i结合使用。
Now, for -it
together. This tells cat that its input is a terminal and in the same time connect this terminal to the input of docker run
which is a terminal. docker run/exec
will make sure that its own input is in fact a tty before passing it to cat
. This is why you will get a input device is not a TTY
if you try echo "hello" | docker run -it alpine cat
because in this case, the input of docker run
itself is the pipe from the previous echo and not the terminal where docker run
is executed
现在,为了 - 在一起。这告诉cat它的输入是一个终端,同时将这个终端连接到docker run的输入端,这是一个终端。 docker run / exec在将它传递给cat之前会确保它自己的输入实际上是一个tty。这就是为什么如果你尝试echo“hello”|你将得到一个输入设备不是TTY的原因docker run -it alpine cat因为在这种情况下,docker run本身的输入是来自前一个echo的管道而不是执行docker run的终端
Finally, why would you need to pass -t
if -i
will do the trick of connecting your input to cat
's input? This is because commands treat the input differently if it's a terminal. This is also best illustrated by example
最后,为什么你需要传递-t如果-i会将输入连接到cat的输入?这是因为如果输入是终端,命令会以不同方式处理输入。这也是最好的例子
-
docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -uroot -p
will give you a password prompt. If you type the password, the characters are printed visibly. -
docker run -i alpine sh
will give you an empty line. If you type a command likels
you get an output, but you will not get a prompt or colored output.
docker run -e MYSQL_ROOT_PASSWORD = 123 -i mariadb mysql -uroot -p会给你一个密码提示。如果键入密码,则会明显打印字符。
docker run -i alpine sh会给你一个空行。如果你输入像ls这样的命令,你会得到一个输出,但你不会得到提示或彩色输出。
In the last two cases, you get this behavior because mysql
as well as shell
were not treating the input as a tty and thus did not use tty specific behavior like masking the input or coloring the output.
在最后两种情况下,你得到这种行为,因为mysql和shell没有将输入视为tty,因此没有使用tty特定的行为,如屏蔽输入或着色输出。
#4
What I know about the -t
is the following:
我对-t的了解如下:
docker exec -ti CONTAINER bash
- allows me to "login" in the container. It feels like ssh-ing (it's not).
docker exec -ti CONTAINER bash - 允许我在容器中“登录”。感觉像sshing(不是)。
But the trouble was when I wanted to restore a database.
但问题是我想要恢复数据库。
Usually I dodocker exec -ti mysql.5.7 mysql
- Here I execute the mysql command in the container and get an interactive terminal.
通常我dodocker exec -ti mysql.5.7 mysql - 这里我在容器中执行mysql命令并获得一个交互式终端。
I added <dump.sql
to the previous command so I can restore a db. But it failed with cannot enable tty mode on non tty input
.
我将
Removing the -t
helped. Still don't understand why:
删除-t有帮助。还是不明白为什么:
docker exec -i mysql.5.7 mysql < dump.sql
The last one works. Hope this helps people.
最后一个有效。希望这有助于人们。
#5
The -it instructs Docker to allocate a pseudo-TTY connected to the container’s stdin, creating an interactive bash shell in the container.
-it指示Docker分配连接到容器stdin的伪TTY,在容器中创建交互式bash shell。
--interactive, -i false Keep STDIN open even if not attached
--tty, -t false Allocate a pseudo-TTY
#1
The "-t" option goes to how Unix/Linux handles terminal access. In the past, a terminal was a hardline connection, later a modem based connection. These had physical device drivers (they were real pieces of equipment). Once generalized networks came into use, a pseudo-terminal driver was developed. This is because it creates a separation between understanding what terminal capabilities can be used without the need to write it into your program directly (read man pages on stty
, curses
).
“-t”选项指向Unix / Linux如何处理终端访问。在过去,终端是强硬连接,后来是基于调制解调器的连接。这些都有物理设备驱动程序(它们是真正的设备)。一旦广义网络投入使用,就开发了伪终端驱动程序。这是因为它在理解可以使用哪些终端功能而无需直接将其写入程序之间创建了分离(阅读stty上的手册页,curses)。
So, with that as background, run a container with no options and by default you have a stdout stream (so docker run | <cmd>
works); run with "-i", and you get stdin stream added (so <cmd> | docker run -i
works); use "-t", usually in the combination "-it" and you have a terminal driver added, which if you are interacting with the process is likely what you want. It basically makes the container start look like a terminal connection session.
因此,以背景为例,运行一个没有选项的容器,默认情况下你有一个stdout流(所以docker run |
#2
The "-t" argument is NOT documented well, or mentioned by many people often, according to a Google search.
根据Google搜索,“-t”参数没有很好地记录,或者很多人经常提到。
It doesn't even show up when you display a list of (what should be) all docker client arguments by typing "docker" at the Bash prompt (with the latest version of 1.8.1).
当您通过在Bash提示符下键入“docker”(使用最新版本的1.8.1)显示所有docker客户端参数的列表时,它甚至不会显示。
In fact, if you try to get specific help about this argument by typing "docker -t --help" if gives this amazingly vague reply:
事实上,如果您尝试通过键入“docker -t --help”获得有关此参数的特定帮助,如果给出了这个非常模糊的回复:
"flag provided but not defined: -t"
“提供了标志但未定义:-t”
So, you can't be blamed for being confused about this argument!
所以,你不能因为对这个论点感到困惑而受到指责!
There is a mention in the Docker online documention which says it is to "Allocate a pseudo-tty" and is often used with -i:
在Docker在线文档中提到它是“分配伪tty”并且经常与-i一起使用:
https://docs.docker.com/reference/run/
I saw it used in the documentation for the terrific jwilder/nginx-proxy docker container in the following way:
我通过以下方式看到它在极好的jwilder / nginx-proxy docker容器的文档中使用:
docker run -d -p 80:80 --name nginx -v /tmp/nginx:/etc/nginx/conf.d -t nginx
In this case, what it does is send the output to the 'virtual' tty (Bash command prompt/terminal) within this docker container. You can then see this output by running the docker command "docker logs CONTAINER" where CONTAINER is the first couple of characters of this container's ID. This CONTAINER ID can be found by typing "docker ps -a"
在这种情况下,它所做的是将输出发送到此docker容器中的'virtual'tty(Bash命令提示符/终端)。然后,您可以通过运行docker命令“docker logs CONTAINER”来查看此输出,其中CONTAINER是此容器ID的前几个字符。输入“docker ps -a”即可找到此CONTAINER ID
I've seen this "-t" argument mentioned briefly in the following link, where it says, "The -t and -i flags allocate a pseudo-tty and keep stdin open even if not attached. This will allow you to use the container like a traditional VM as long as the bash prompt is running."
我在下面的链接中看到过这个“-t”参数,它说:“-t和-i标志分配一个伪tty并保持stdin打开,即使没有附加。这将允许你使用只要bash提示符正在运行,就像传统的VM一样容器。“
https://coreos.com/os/docs/latest/getting-started-with-docker.html
I hope this helps! I'm not sure why this isn't documented or used much. Maybe it's experimental and will be implemented as a documented feature in upcoming versions.
我希望这有帮助!我不确定为什么没有记录或使用太多。也许它是实验性的,并将在即将推出的版本中作为文档功能实现。
#3
Late answer, but might help someone
迟到的答案,但可能会帮助某人
docker run/exec -i
will connect the STDIN of the command inside the container to the STDIN of the docker run/exec
itself.
docker run / exec -i将容器内的命令的STDIN连接到docker run / exec本身的STDIN。
So
-
docker run -i alpine cat
gives you an empty line waiting for input. Type "hello" you get an echo "hello". The container will not exit until you send CTRL+D because the main processcat
is waiting for input from the infinite stream that is the terminal input of thedocker run
. - On the other hand
echo "hello" | docker -i run alpine cat
will print "hello" and exit immediately becausecat
notices that the input stream has ended and terminates itself.
docker run -i alpine cat给你一个空行等待输入。键入“你好”你得到一个回声“你好”。在发送CTRL + D之前容器不会退出,因为主进程cat正在等待来自无限流的输入,该无限流是docker run的终端输入。
另一方面回声“你好”| docker -i run alpine cat将打印“hello”并立即退出,因为cat注意到输入流已经结束并终止自身。
If you try docker ps
after you exit either of the above, you will not find any running containers. In both cases, cat
itself has terminated, thus docker has terminated the container.
如果在退出上述任何一个之后尝试使用docker ps,则无法找到任何正在运行的容器。在这两种情况下,cat本身都已终止,因此docker已终止容器。
Now for "-t", this tells the main process inside docker that its input is a terminal device.
现在为“-t”,这告诉docker内部的主进程它的输入是终端设备。
So
-
docker run -t alpine cat
will give you an empty line, but if you try to type "hello", you will not get any echo. This is because whilecat
is connected to a terminal input, this input is not connected to your input. The "hello" that you typed did not reach the input ofcat
.cat
is waiting for input that never arrives. -
echo "hello" | docker run -t alpine cat
will also give you an empty line and will not exit the container on CTRL-D but you will not get an echo "hello" because you didn't pass-i
docker run -t alpine cat会给你一个空行,但是如果你试着键入“hello”,你就不会得到任何回音。这是因为当cat连接到终端输入时,此输入未连接到您的输入。你输入的“hello”没有达到cat的输入。猫正等待从未到过的输入。
echo“你好”| docker run -t alpine cat也会给你一个空行并且不会在CTRL-D上退出容器,但你不会得到一个echo“hello”,因为你没有通过-i
If you send CTRL+C, you get your shell back, but if you try docker ps
now, you see the cat
container still running. This is because cat
is still waiting on an input stream that was never closed. I have not found any useful use for the -t
alone without being combined with -i
.
如果你发送CTRL + C,你会得到你的shell,但如果你现在尝试使用docker ps,你会看到cat容器仍在运行。这是因为cat仍在等待从未关闭的输入流。我没有找到任何有用的-t单独使用而不与-i结合使用。
Now, for -it
together. This tells cat that its input is a terminal and in the same time connect this terminal to the input of docker run
which is a terminal. docker run/exec
will make sure that its own input is in fact a tty before passing it to cat
. This is why you will get a input device is not a TTY
if you try echo "hello" | docker run -it alpine cat
because in this case, the input of docker run
itself is the pipe from the previous echo and not the terminal where docker run
is executed
现在,为了 - 在一起。这告诉cat它的输入是一个终端,同时将这个终端连接到docker run的输入端,这是一个终端。 docker run / exec在将它传递给cat之前会确保它自己的输入实际上是一个tty。这就是为什么如果你尝试echo“hello”|你将得到一个输入设备不是TTY的原因docker run -it alpine cat因为在这种情况下,docker run本身的输入是来自前一个echo的管道而不是执行docker run的终端
Finally, why would you need to pass -t
if -i
will do the trick of connecting your input to cat
's input? This is because commands treat the input differently if it's a terminal. This is also best illustrated by example
最后,为什么你需要传递-t如果-i会将输入连接到cat的输入?这是因为如果输入是终端,命令会以不同方式处理输入。这也是最好的例子
-
docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -uroot -p
will give you a password prompt. If you type the password, the characters are printed visibly. -
docker run -i alpine sh
will give you an empty line. If you type a command likels
you get an output, but you will not get a prompt or colored output.
docker run -e MYSQL_ROOT_PASSWORD = 123 -i mariadb mysql -uroot -p会给你一个密码提示。如果键入密码,则会明显打印字符。
docker run -i alpine sh会给你一个空行。如果你输入像ls这样的命令,你会得到一个输出,但你不会得到提示或彩色输出。
In the last two cases, you get this behavior because mysql
as well as shell
were not treating the input as a tty and thus did not use tty specific behavior like masking the input or coloring the output.
在最后两种情况下,你得到这种行为,因为mysql和shell没有将输入视为tty,因此没有使用tty特定的行为,如屏蔽输入或着色输出。
#4
What I know about the -t
is the following:
我对-t的了解如下:
docker exec -ti CONTAINER bash
- allows me to "login" in the container. It feels like ssh-ing (it's not).
docker exec -ti CONTAINER bash - 允许我在容器中“登录”。感觉像sshing(不是)。
But the trouble was when I wanted to restore a database.
但问题是我想要恢复数据库。
Usually I dodocker exec -ti mysql.5.7 mysql
- Here I execute the mysql command in the container and get an interactive terminal.
通常我dodocker exec -ti mysql.5.7 mysql - 这里我在容器中执行mysql命令并获得一个交互式终端。
I added <dump.sql
to the previous command so I can restore a db. But it failed with cannot enable tty mode on non tty input
.
我将
Removing the -t
helped. Still don't understand why:
删除-t有帮助。还是不明白为什么:
docker exec -i mysql.5.7 mysql < dump.sql
The last one works. Hope this helps people.
最后一个有效。希望这有助于人们。
#5
The -it instructs Docker to allocate a pseudo-TTY connected to the container’s stdin, creating an interactive bash shell in the container.
-it指示Docker分配连接到容器stdin的伪TTY,在容器中创建交互式bash shell。
--interactive, -i false Keep STDIN open even if not attached
--tty, -t false Allocate a pseudo-TTY