Поздний ответ, но может кому-то помочь
docker run/exec -i
подключит STDIN команды внутри контейнера к STDIN команды docker run/exec
сам.
Так
-
docker run -i alpine cat
выдает вам пустую строку, ожидающую ввода. Введите "привет", вы получите эхо "привет". Контейнер не завершится, пока вы не отправите CTRL + D, потому что основной процессcat
ожидает ввода из бесконечного потока, который является терминальным входомdocker run
. - С другой стороны
echo "hello" | docker run -i alpine cat
напечатает "привет" и немедленно завершит работу, потому чтоcat
замечает, что входной поток закончился, и завершает сам себя.
Если вы попытаетесь docker ps
после того, как вы завершите любой из вышеперечисленных действий, вы не найдете никаких запущенных контейнеров. В обоих случаях, cat
сам завершается, таким образом, docker завершает работу контейнера.
Теперь для "-t" это сообщает основному процессу внутри docker, что его ввод является терминальным устройством.
Так
-
docker run -t alpine cat
выдаст вам пустую строку, но если вы попытаетесь ввести "привет", вы не получите никакого эха. Это происходит потому, что в то время какcat
подключен к входу терминала, этот вход не подключен к вашему входу. Введенное вами "привет" не дошло до вводаcat
.cat
ожидает ввода, который никогда не поступает. -
echo "hello" | docker run -t alpine cat
также выдаст вам пустую строку и не выйдет из контейнера при нажатии CTRL-D, но вы не получите эхо "привет", потому что вы не прошли-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
потому что в этом случае ввод docker run
сам по себе является каналом из предыдущего echo, а не терминалом, где docker run
выполняется
Наконец, зачем вам нужно проходить -t
если -i
сделает трюк с подключением вашего ввода к cat
чей вклад? Это связано с тем, что команды обрабатывают ввод по-разному, если это терминал. Это также лучше всего иллюстрируется примером
-
docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -uroot -p
выдаст вам запрос на ввод пароля. Если вы вводите пароль, символы печатаются на видном месте. -
docker run -i alpine sh
даст вам пустую строку. Если вы введете команду типаls
вы получите вывод, но вы не получите подсказку или цветной вывод.
В последних двух случаях вы получаете такое поведение, потому что mysql
так же как shell
не обрабатывали входные данные как tty и, следовательно, не использовали специфичное для tty поведение, такое как маскирование входных данных или раскрашивание выходных данных.