4

I often use these command line options, -i and -t when working with containers that I want to interact with.

  -i, --stdin=false: Pass stdin to the container
  -t, --tty=false: Stdin is a TTY

How do these work for making the containers interactive?

Logica
  • 977
  • 4
  • 16
Senthil Kumaran
  • 54,681
  • 14
  • 94
  • 131
  • I usually interact with containers by making network calls to them, so I don’t need these options. What sort of answer are you looking for; a pointer into the Docker source code? – David Maze Jan 29 '20 at 14:30
  • A pointer to a good tutorial, a high-level accurate explanation. Pointer to docker source code should be okay too if it supplements the high-level explanation. – Senthil Kumaran Jan 29 '20 at 14:40
  • Does this answer your question? [what is docker run -it flag?](https://stackoverflow.com/questions/48368411/what-is-docker-run-it-flag) – jannis Jan 29 '20 at 15:58

1 Answers1

5

When you use -i option, the client (i.e., docker command) is attaching itself to the stdin of the command inside the container. If you use -t option, you are also attaching a terminal to the command. Some programs behave differently when connected to a terminal.


bash-3.2$ docker run -i ubuntu cat
Hey    <-- input from my stdin
Hey    --> output from cat
Hello  <-- input from my stdin
Hello  --> output from cat

cat command's stdin is connected to docker run command's stdin.


bash-3.2$ echo Hey | docker run -i ubuntu cat
Hey    --> output from cat

Here, the stdin of cat command is connected to stdin of docker run which is connected to stdout of echo. docker run exits as soon as the stdin is disconnected.


bash-3.2$ docker run -it ubuntu cat
Hey    <-- input from my stdin
Hey    --> output from cat

The stdin of cat is connected to a tty input. This tty is connected to stdin of docker run. stdin of docker run must also be a tty.

Not sure if cat behaves any differently if it's stdin is tty, but many other programs do. Example: Some commands might hide the input when taking password input from a tty.


bash-3.2$ echo Hey | docker run -it ubuntu cat
the input device is not a TTY

docker run command's stdin is not a tty. So it cannot be connected to tty connected to cat command's stdin.


bash-3.2$ docker run -t ubuntu cat
Hey    <-- input from my stdin. no output from cat

cat command's stdin is connected to tty and that's it. docker run command's stdin is NOT connected to the cat because -i option is not used. So even you type anything into your stdin, it won't reach cat.


bash-3.2$ echo Hey | docker run -t ubuntu cat

cat command's stdin is connected to tty and that's it. Output of echo won't reach cat.


How do these work for making the containers interactive?

Client makes an API call at /containers/{id}/attach to the docker daemon. This HTTP connection is then hijacked to transport the stdin, stdout, and stderr(depending on options) over the underlying socket. Client and server use this socket for bidirectional streaming.

Depending on whether tty is enabled, the stream format might vary. From container_attach.go:

// If the container is using a TTY, there is only a single stream (stdout), and
// data is copied directly from the container output stream, no extra
// multiplexing or headers.
//
// If the container is *not* using a TTY, streams for stdout and stderr are
// multiplexed.
// The format of the multiplexed stream is as follows:
//
//    [8]byte{STREAM_TYPE, 0, 0, 0, SIZE1, SIZE2, SIZE3, SIZE4}[]byte{OUTPUT}
//
// STREAM_TYPE can be 1 for stdout and 2 for stderr
//
// SIZE1, SIZE2, SIZE3, and SIZE4 are four bytes of uint32 encoded as big endian.
// This is the size of OUTPUT.

On the client side, the data from stream is copied onto it's stdout and it's stdin is copied onto the stream.

Shashank V
  • 10,007
  • 2
  • 25
  • 41