Подтвердить что ты не робот

Когда я буду использовать `--interactive` без` -tty` в контейнере Docker?

Я сделал несколько поисковых запросов и не повезло найти случай, когда я бы выполнил docker run -i some_image, а не docker run -it some_image.

Если я запустил docker run -i --name sample some_image bash, контейнер запускается на переднем плане, но я не могу взаимодействовать с ним из оболочки, в которой я находится. Я даже не могу остановить ее с помощью CTRL + C. Однако я могу открыть другую оболочку и запустить docker exec -it sample bash и получить доступ к контейнеру.

Если я запустил docker run -i -d --name sample some_image bash, контейнер немедленно выйдет. Я могу перезапустить его с помощью docker start sample, а затем он останется, поэтому я могу запустить docker exec -it sample bash и снова взаимодействовать с ним.

Однако во всех этих случаях я в конечном итоге использую -it для взаимодействия с моими контейнерами. В каком мире мне не нужен флаг -t?

Приветствия

4b9b3361

Ответ 1

Так как -i сохраняет STDIN открытым, даже если он не подключен, он позволяет создавать композицию (трубопровод).
Например:

docker run ubuntu printf "line1\nline2\n" | docker run -i ubuntu grep line2 | docker run -i ubuntu sed 's/line2/line3/g'

(Источник: issue 14221)

Или:

$ echo hello | docker run -i busybox cat
  hello

(Источник: issue 12401)

Теперь представьте себе, что это не перед клавиатурой и используется в script, где вы действительно можете написать процессам stdin через что-то лучше, чем оболочка |: example integration-cli/docker_cli_attach_test.go

Ответ 2

Поздний ответ, но может помочь кому-то

docker run/exec -i подключит STDIN команды внутри контейнера к STDIN самого docker run/exec.

Так

  • docker run -i alpine cat выдает пустую строку в ожидании ввода. Типа "привет", вы получаете эхо "привет". Контейнер не выйдет до тех пор, пока вы не отправите CTRL + D, потому что основной процесс cat ожидает ввода из бесконечного потока, который является входом терминала для docker run.
  • С другой стороны, echo "hello" | docker -i run alpine cat echo "hello" | docker -i run alpine cat выведет "hello" и немедленно выйдет, потому что cat замечает, что поток ввода закончился и завершает сам.

Если вы попробуете docker ps после выхода из любого из вышеперечисленных, вы не найдете никаких работающих контейнеров. В обоих случаях сам cat завершил работу, поэтому docker завершил работу с контейнером.

Теперь для "-t" это говорит основному процессу внутри докера, что его вход является терминальным устройством.

Так

  • docker run -t alpine cat выдаст вам пустую строку, но если вы попытаетесь напечатать "hello", вы не получите никакого эха. Это потому, что хотя cat подключен к входу терминала, этот вход не подключен к вашему входу. "Привет", который вы набрали, не дошел до ввода cat. cat ждет ввода, который никогда не прибудет.
  • echo "hello" | docker run -t alpine cat echo "hello" | docker run -t alpine cat также выдаст вам пустую строку и не выйдет из контейнера на CTRL-D, но вы не получите эхо "hello", потому что вы не прошли -i

Если вы отправите CTRL + C, вы вернете свою оболочку, но если вы попробуете docker ps сейчас, вы увидите, что контейнер cat все еще работает. Это связано с тем, что cat по-прежнему ожидает входной поток, который никогда не был закрыт. Я не нашел никакого полезного использования только для -t без сочетания с -i.

Теперь для -it вместе. Это говорит cat, что его вход является терминалом, и в то же время подключите этот терминал к входу docker run который является терминалом. docker run/exec удостоверится в том, что его собственный ввод фактически является tty, прежде чем передать его в cat. Вот почему вы получите input device is not a TTY если вы попробуете echo "hello" | docker run -it alpine cat echo "hello" | docker run -it alpine cat потому что в этом случае вход docker run сам по себе является каналом от предыдущего эха, а не терминалом, где docker run

Наконец, зачем вам передавать -t если -i выполнит трюк, соединяющий ваш вход со входом cat? Это потому, что команды обрабатывают ввод по-разному, если это терминал. Это также лучше всего иллюстрируется на примере

  • docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -uroot -p выдаст запрос на docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -uroot -p пароля. Если вы введете пароль, символы будут напечатаны визуально.
  • docker run -i alpine sh выдаст вам пустую строку. Если вы наберете команду типа ls вы получите вывод, но вы не получите подсказку или цветной вывод.

В последних двух случаях вы получаете такое поведение, потому что mysql а также shell не обрабатывали ввод как tty и, следовательно, не использовали специфическое для tty поведение, такое как маскирование ввода или окрашивание вывода.