Когда вы используете опцию -i
, клиент (т. Е. Команда docker
) присоединяется к стандартному вводу команды внутри контейнера. Если вы используете опцию -t
, вы также присоединяете терминал к команде. Некоторые программы ведут себя по-разному при подключении к терминалу.
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
Стандарт команды подключен к docker run
Стандарт команды.
bash-3.2$ echo Hey | docker run -i ubuntu cat
Hey --> output from cat
Здесь стандартный ввод команды cat
подключен к стандартному вводу docker run
, который подключен к стандартному выводу echo
. docker run
выходит, как только stdin отключен.
bash-3.2$ docker run -it ubuntu cat
Hey <-- input from my stdin
Hey --> output from cat
Stdin cat
подключен к tty-входу. Этот tty подключен к стандартному вводу docker run
. stdin из docker run
также должен быть tty.
Не уверен, что cat ведет себя иначе, если это stdin tty, но многие другие программы делают. Пример: Некоторые команды могут скрывать ввод при получении пароля от tty.
bash-3.2$ echo Hey | docker run -it ubuntu cat
the input device is not a TTY
docker run
Стандартом команды не является tty. Поэтому он не может быть подключен к tty, подключенному к cat
стандартному значению команды.
bash-3.2$ docker run -t ubuntu cat
Hey <-- input from my stdin. no output from cat
cat
Стандартный командный элемент подключен к tty и все. Команда docker run
stdin НЕ подключена к cat
, поскольку опция -i
не используется. Таким образом, даже если вы введете что-либо в свой стандартный ввод, оно не достигнет cat
.
bash-3.2$ echo Hey | docker run -t ubuntu cat
cat
Стандар команды подключен к tty и все. Выход echo
не достигнет cat
.
Как это работает для создания интерактивных контейнеров?
Клиент делает вызов API в /containers/{id}/attach
в docker демон. Это HTTP-соединение затем захватывается для передачи stdin
, stdout
и stderr
(в зависимости от параметров) через базовый сокет. Клиент и сервер используют этот сокет для двунаправленной потоковой передачи.
В зависимости от того, включен ли tty, формат потока может отличаться. Начиная с 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.
На стороне клиента данные из потока копируются в его стандартный вывод и это стандартный копируется на поток .