什么是docker run -it标志?

224

我正在使用Docker进行一些复杂的操作,但是发现我不知道-it标志的含义。 最近我遇到了一些docker run命令的示例,让我有些困惑。

docker run -itd ubuntu:xenial /bin/bash 

我的问题是,在容器实例化期间运行bin/bash的情况下,写-it标志有何意义?
在文档中我们有一个例子。
docker run --name test -it debian

带有解释

-it指示Docker为容器的stdin分配一个伪TTY;在容器中创建一个交互式的bash shell。

-t标志的说明来自帮助页面

-t,--tty 分配伪终端

如果我在运行命令时删除-it标志

docker run -d ubuntu:xenial /bin/bash

我新创建的容器没有持续运行,

docker ps -a中被标记为已退出。

抱歉,如果我的问题很愚蠢,我在互联网上找不到解释(我对这一点有很大的误解)。


1
如果/bin/bash在标准输入上没有可用的内容,则它没有要运行的命令和提示用户的方式,因此它会退出。这是100%正常和预期的行为。 - Charles Duffy
4个回答

207

-it--interactive--tty 的缩写。当你使用这个命令运行 docker run 时,它会直接将你带到容器内部。

-d--detach 的缩写,意味着你只是运行容器而已,随后就会与其分离。基本上,你在后台运行容器。

编辑:因此,如果你使用-itd 运行 Docker 容器,它将同时运行 -it 选项并将你与容器分离。结果是,即使没有任何默认应用程序运行,你的容器仍将在后台运行。


2
这意味着您的容器存在错误,因此无法启动。或者可能默认情况下没有任何CMD命令,因此默认情况下未运行任何应用程序。因此,如果在后台运行它,它将立即退出,因为它没有任何工作要做。 - Fendi jatmiko
1
@Alex,如果你容器中的程序是在stdin关闭时退出的,那么这就是为什么它没有使用“-i”选项就无法运行的答案。同样地,如果它运行的命令根据是否有TTY而表现出不同的行为,那么你可以根据是否存在“-t”来获得不同的行为。 - Charles Duffy
2
@Alex,...并且要明确的是,如果你在没有Docker的情况下运行/bin/bash </dev/null,它也会立即退出。在没有使用-i的情况下运行docker run,对于它启动的bash副本来说也是一样的。(没有-t,它有一个标准输入但没有TTY,所以它不会将自己检测为交互式shell,因此您会得到略微不同的行为)。 - Charles Duffy
1
我发现添加-it解决了容器中编译器不输出彩色编译错误的问题,但我不知道为什么会解决这个问题,因为我认为-it只与标准输入和交互式用户输入有关,与标准输出无关... 有人可以解释一下吗?可能是一个bug吗?看起来-it让gcc意识到它是一个真正的终端并以彩色输出错误。没有-it就没有颜色... - AdmiralAdama
2
@AdmiralAdama,修复颜色问题的方法是使用-t选项。需要TTY来理解颜色标记。 - kroiz
显示剩余3条评论

69

docker run -it ubuntu:xenial /bin/bash 以交互模式启动容器(即使用-it标志),允许您与容器中的/bin/bash进行交互。这意味着现在您将拥有容器内的bash会话,因此您可以在容器内执行lsmkdir或任何bash命令。

关键在于单词“interactive”。如果省略该标志,则容器仍会执行/bin/bash但会立即退出。使用该标志后,容器会执行/bin/bash,然后等待您的输入。


4
那么我需要使用-t标志做什么呢? docker run -i ubuntu:xenial /bin/bash - Alex
13
你是正确的。我会收回我的话。即使没有 -t 标签,你仍然可以与容器进行交互,但使用它可以获得更好、更多功能的终端。你可以使用 -i-it 来运行并比较差异。 - dvnguyen
@dvnguyen 当单独使用“-i”时,缺少哪个重要功能?我还想知道“-i”和“-it”的区别。 - Blupon

9

无任何标志的正常执行:

[ec2-user@ip-172-31-109-14 ~]$ sudo docker exec 69e937450dab ls
bin
boot
dev
docker-entrypoint.d
docker-entrypoint.sh
etc

如果您的命令需要像cat一样的输入,您可以尝试:
[ec2-user@ip-172-31-109-14 ~]$ echo test | sudo docker exec 69e937450dab cat

什么也不会显示,因为没有输入流传递到Docker容器中。可以通过-i标志实现此目的。

[ec2-user@ip-172-31-109-14 ~]$ echo test | sudo docker exec -i 69e937450dab cat
test

现在,假设您希望Bash作为进程启动:
sudo docker exec 69e937450dab bash

由于该进程是在容器中启动的,因此您将看不到任何内容。添加标志将解决此问题:

[ec2-user@ip-172-31-109-14 ~]$ sudo docker exec -t 69e937450dab bash
root@69e937450dab:/# 

但是这并没有真正帮助我们,因为我们需要一个输入流,可以接受我们的命令并被bash接收。因此,我们需要将两者结合起来:

[ec2-user@ip-172-31-109-14 ~]$ sudo docker exec -i -t 69e937450dab bash
root@69e937450dab:/# ls
bin  boot  dev  docker-entrypoint.d  docker-entrypoint.sh  etc  hi  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@69e937450dab:/# 

小结:

-t 用于将Bash进程连接到我们的终端。

-i 使我们能够通过标准输入(例如使用键盘)向容器中的Bash发送输入。

没有-i选项可用于不需要输入的命令。当您不想将Docker容器的进程连接到您的shell时,可以不带-t和Bash使用。


4

我想为像我这样的新手添加一些直观的解释。

-it 是用于命令 docker rundocker container run 的标志(它们是别名)。建议你了解一下这些标志并继续往下看:

  • -i--interactive
    当你输入 docker run -i 时,这意味着你的终端会将你的输入传递给容器(容器中的应用程序),直到你按下 ctrl-D(离开容器)。例如,如果某个应用程序在容器中等待用户输入,你可以输入一些内容,然后它会被转发给应用程序。
  • -t-tty(伪终端):
    如果你添加了这个标志,容器的输出会附加到你的终端上。它主要与输出格式有关(例如对于 bin/bash,尝试使用和不使用 -t 标志的 ls 命令),但有时更重要的是,因为某些应用程序会根据是通过终端启动还是其他方式启动而改变其行为(例如文本编辑器,或者终端实现的密码屏蔽机制使用 *)。
将两个标志组合为-it,可以让您的容器获取标准输入并从容器中获得漂亮的格式化输出,就像您正在使用自己的终端一样。 后续操作:
Docker如何知道哪个应用程序将获取我的标准输入(stdin)?当您键入`docker run -i `时,最后一个参数(``)将获取您的输入。
这两个标志各自的实际应用是什么? - `-i`在您希望与容器中的应用程序进行交互,但对于您来说获取格式化输出并不重要时非常有用。例如,您希望将数据发送到容器中,从中获取数据并将其保存到文件中。在这种情况下,`-t`是不必要的。
```bash echo "my input" | docker run -i > output.txt ```
- `-t`在您希望获得类似终端的输出,但不需要将输入传输到容器中时非常有用。假设您有一个在容器内部启动的脚本,以特定格式输出数据,然后另一个脚本使用该数据:
```bash docker run -t my-image | my-processing-script.sh ```

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接