100

I read some docker docs and I do not understand what it might mean to

  • attach a tty
  • attach std-in and std-out

for these purposes, I see that -i and -t flags are use.

What does this process mean?

Kromster
  • 7,181
  • 7
  • 63
  • 111
Phil
  • 13,875
  • 21
  • 81
  • 126

5 Answers5

97

stdin, stdout, and ttys are related concepts. stdin and stdout are the input and output streams of a process. A pseudo terminal (also known as a tty or a pts) connects a user's "terminal" with the stdin and stdout stream, commonly (but not necessarily) through a shell such as bash. I use quotes around "terminal" since we really don't use a terminal in the same sense today.

In the case of docker, you'll often use -t and -i together when you run processes in interactive mode, such as when starting a bash shell. In the case of the shell you want to be able to issue commands and read the output.

The code docker uses to attach stdout/stdin has all the dirty details.

Ben Whaley
  • 32,811
  • 7
  • 87
  • 85
  • 1
    In docker 1.2.0 all commands above succeed and display `hello` with no errors. – Air Sep 23 '14 at 15:11
  • When I exit from psuedo terminal, it means docker container is stopped. So does it mean that if I use it on actual project I cannot exit the terminal? – NothingBox May 02 '20 at 13:05
39

We can see what is happening under the hood by using the lsof command. For a demonstration we can create a simple docker container from a Debian image that just runs sleep:

docker run -d --name tty-test debian /bin/bash -c "sleep 1000"

This will start the sleep command in a new container (note that we did not use -i or -t).

Next we "login" into our container though the exec command and start a bash:

docker exec -it tty-test /bin/bash

A plain debian image will not have lsof installed so we need to install it:

apt update && apt install -y lsof

Next we run lsof:

lsof

If run without any options, lsof will print open files for all running processes. You should see three processes in its output (sleep, bash, and lsof itself).

Here are the relevant lines are those that show the file descriptors (FD column) 0 to 2.

Note how the sleep process, which we started without the -t option has three FIFO pipes for stdin,stdout and stderr:

sleep     1 root    0r  FIFO   0,10      0t0 8226490 pipe
sleep     1 root    1w  FIFO   0,10      0t0 8226491 pipe
sleep     1 root    2w  FIFO   0,10      0t0 8226492 pipe

While the bash process has an actual device attached to stdin, stdout and stderr:

bash      7 root    0u   CHR 136,15      0t0      18 /dev/pts/15
bash      7 root    1u   CHR 136,15      0t0      18 /dev/pts/15
bash      7 root    2u   CHR 136,15      0t0      18 /dev/pts/15

Lets create another container with the -t option:

docker run -d -t --name tty-test2 debian /bin/bash -c "sleep 1000"

After installing lsof again (see above) we get a different output from lsof for the sleep process:

sleep     1 root    0u   CHR 136,15      0t0      18 /15
sleep     1 root    1u   CHR 136,15      0t0      18 /15
sleep     1 root    2u   CHR 136,15      0t0      18 /15

Note how the type column has changed to CHR and the name column shows /15.

Finally, when we omit the -t option from the exec command and like this:

docker exec -it tty-test /bin/bash

then we can notice two things. First, we do not get a shell prompt from the bash now, but we can still type commands and see their output. When we run lsof we see that the bash process now also has pipes rather then a tty attached to stdin, stdout, and stderr

bash    379 root    0r  FIFO   0,10      0t0 8263037 pipe
bash    379 root    1w  FIFO   0,10      0t0 8263038 pipe
bash    379 root    2w  FIFO   0,10      0t0 8263039 pipe
lanoxx
  • 12,249
  • 13
  • 87
  • 142
  • 2
    Good analysis. What if instead of `-d -t` you just do `-t`? Also, what if you pass `--entrypoint` to the `sleep` (no bash)? – dashesy Mar 10 '17 at 06:07
  • 1
    thanks for your answer! I'm wondering what does running a container in daemon mode with terminal actually give me? – Guy Apr 15 '20 at 21:42
9

It means you can log in to your container using TTY, ie terminal. It's as if you've got a Linux machine in front of you and you're logging into it. If you have a container that's not running SSH server or telnet, this is your only mode of getting into the command line prompt.

As for why -i and -t are different arguments I'm not sure about, I can't imagine a scenario where you want to connect using TTY and don't want the stdin/stdout option or vice versa.

Reza S
  • 9,480
  • 3
  • 54
  • 84
4

Option -i -t is useful for interacting with certain interactive process's like bash shell running inside the container.

consider the below command

PS C:\Users\nssh> docker run -it ubuntu /bin/bash
root@c7537bbf2941:/# ls
bin  boot  dev  etc  home  lib  lib32  lib64

When we run this command, docker will start the ubuntu container with bash shell running inside.

  • The -i flag tells docker that anything we type should be sent to bash process's stdin. ls command typed above is sent to bash.

  • The -t flag tells docker that this will be an interactive session and the stdin will be a tty.

For a typical SSH like experience, -t and -i must be used together.

The only reason to leave out -t is if the stdin is a pipe (and not a tty like above). Specifying -t is forbidden when the client is receiving its standard input from a pipe, as in:

PS C:\Users\nssh> echo test | docker run -it ubuntu cat
the input device is not a TTY.  If you are using mintty, try prefixing the command with 'winpty'

Leave out the -t flag if stdin is a pipe.

PS C:\Users\nssh> echo test | docker run -i ubuntu cat
test
ns15
  • 5,604
  • 47
  • 51
1

Simply put it allows us to attach and detach from the containers terminal. To attach we use the docker attach command and to detach we use the CTRL+P & CTRL+Q command.

user7780
  • 31
  • 5