의사 TTY를 할당하는 Docker -t 옵션에 대해 혼동


206

이 옵션은 정확히 무엇을합니까? 나는 TTY에 대해 많은 것을 읽었으며 여전히 혼란스러워합니다. 나는를 가지고 있지 함께 놀았 -t그냥 -i그것은 사용자 입력이없이 오류가 발생 기대할 프로그램처럼 보인다 -t. pseudo-TTY를 활성화하는 것이 중요한 이유는 무엇입니까?

답변:


223

-t옵션은 유닉스 / 리눅스 터미널 접속을 처리하는 방법에 간다. 과거에는 터미널이 유선 연결이었고 나중에 모뎀 기반 연결이었습니다. 여기에는 실제 장치 드라이버가있었습니다 (실제 장비였습니다). 일반화 된 네트워크가 사용되면 의사 터미널 드라이버가 개발되었습니다. 이 터미널 기능 (남자 페이지를 읽고 직접 프로그램으로 작성할 필요없이 사용할 수있는 이해 사이의 분리를 생성하기 때문입니다 stty, curses).

따라서 배경으로 옵션없이 컨테이너를 실행하고 기본적으로 stdout 스트림이 있습니다 ( docker run | <cmd>작동합니다). 로 실행 -i하면 stdin 스트림이 추가됩니다 (그래서 <cmd> | docker run -i작동합니다). -t일반적으로 조합하여을 사용 -it하고 터미널 드라이버가 추가되어 프로세스와 상호 작용하는 경우 원하는 것 같습니다. 기본적으로 컨테이너 시작은 터미널 연결 세션처럼 보입니다.


7
이것이 최고의 답변이되어야합니다. 가장 기술적 인 것은 아니지만 -it플래그 의 기본 동작을 설명합니다 .
Kris Khaira

1
크리스와 동의하십시오. 나는 다른 답변을 읽었으며 여전히 완전히 혼란 스러웠다. 이 대답은 그것을 정리합니다.
Ben Lee

3
예, "TTY"자체는 전화처럼 텍스트를 입력하고 동시에 보낼 수있는 장치의 이름 인 "teletypewriter"(일명 "teleprinter")에서 나오는 약어입니다. 텍스트 ;-) 시도 docker run -i ubuntu하고 docker run -it ubuntu즉시 차이를 볼 수 있습니다. "-i"를 사용하면 컨테이너가 호스트와의 상호 작용을 기다릴 수 있지만 "tty driver"를 "-t"플래그와 함께 할당 한 후 콘솔 (터미널)과의 실제 상호 작용이 가능합니다.
Zegar

도커 내에서 tty를 시작할 수 있습니까? 작동하지 않는 앱이 있습니다. 도커를 실행하지 않지만 -t프로덕션에서 docker start 명령을 수정할 수 없습니다. 따라서 앱이로 시작되었다고 생각하도록해야합니다 -t.
mvorisek 2016 년

97

늦은 답변이지만 누군가를 도울 수 있습니다

docker run/exec -i컨테이너 내부의 명령의 STDIN을 docker run/exec자체 의 STDIN에 연결 합니다.

그래서

  • docker run -i alpine cat입력을 기다리는 빈 줄을 제공합니다. "hello"를 입력하면 에코 "hello"가 나타납니다. 기본 프로세스 가의 터미널 입력 인 무한 스트림의 입력을 기다리고 있으므로 CTRL+ 를 보낼 때까지 컨테이너가 종료되지 않습니다 .Dcatdocker run
  • 반면에 echo "hello" | docker run -i alpine cat"hello"를 인쇄 cat하고 입력 스트림이 종료되었다는 것을 알기 때문에 즉시 종료됩니다.

docker ps위 중 하나를 종료 한 후에 시도 하면 실행중인 컨테이너가 없습니다. 두 경우 모두 cat자체가 종료되었으므로 docker가 컨테이너를 종료했습니다.

이제 "-t"의 경우 도커 내부의 기본 프로세스에 입력이 터미널 장치임을 알립니다.

그래서

  • docker run -t alpine cat빈 줄을 줄 것입니다. 그러나 "hello"를 입력하면 에코가 나타나지 않습니다. while cat이 터미널 입력에 연결되어 있기 때문에이 입력이 입력에 연결되지 않았기 때문 입니다. 입력하신 "hello"가에 입력되지 않았습니다 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되는 곳 docker run이 아닌 이전 에코의 파이프 이기 때문에 시도 하면 결과를 얻을 수 있습니다.

마지막으로, 당신은 왜 전달해야 할 -t경우 -i에 입력을 연결하는 트릭을 할 것 cat'의 입력을? 명령이 입력 인 경우 명령이 입력을 다르게 취급하기 때문입니다. 이것은 또한 예제로 가장 잘 설명됩니다.

  • docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -u root -p비밀번호 프롬프트가 표시됩니다. 암호를 입력하면 문자가 표시됩니다.
  • docker run -i alpine sh빈 줄을 줄 것입니다. ls출력 과 같은 명령을 입력하면 프롬프트 나 컬러 출력이 표시되지 않습니다.

마지막 두 경우에, 당신은 때문에이 동작을 얻을 mysql뿐만 아니라 같이 shell입력을 마스킹하거나 출력을 착색처럼 TTY 특정 동작을 사용하지 않은, 따라서 청각 장애로 입력을 처리되지 않은합니다.


6
여기에서 가장 좋은 답변은 정확히 무엇 -t이고 -i옵션이 무엇인지 이해하게 해줍니다 !
Ruslan Stelmachenko

1
내가 가진 모든 질문을 예상했던 환상적인 답변
James Machin

@Ahmed Ghonim, 아주 좋은 답변입니다. 감사합니다. 그러나 "이것은 명령이 입력 인 경우 명령이 입력을 다르게 취급하기 때문"이라고 생각합니다. "이것은 명령이 입력이 아닌 경우 명령이 입력을 다르게 취급하기 때문 "입니다.
tuq

@Ahmed Ghonim. 맑은. 그러나 docker run -a = stdin alpine cat은 어떻습니까?
HKIT

1
@HKIIT "-a = stdin"은 stdin 스트림을 컨테이너에 연결하지만 메모리 할당은 없습니다. stdin 스트림의 컨테이너에 버퍼 메모리를 할당하는 -i 플래그입니다. 따라서 -i가 전달 될 때 "STDIN이 연결되어 있지 않아도 계속 열려 있습니다"라는 설명은 첨부 파일 플래그에 관계없이 stdin에 메모리가 할당됩니다. 이 할당 된 메모리가 없으면 stdin에 대한 읽기가 비어 있습니다. 또한 cat 명령의 응답을 보려면 "-a = stdout"을 포함해야합니다 (예 : "docker run -i -a = stdin -a = stdout alpine cat") ... 물론이 작업을 수행 할 필요는 없습니다. "docker run -i alpine cat"을 실행하십시오.
데이비드 D

71

-t구글 검색에 따르면 이 주장은 잘 문서화되어 있지 않거나 많은 사람들이 자주 언급하고있다.

dockerBash 프롬프트 (최신 버전 1.8.1) 를 입력하여 모든 도커 클라이언트 인수 목록을 표시 할 때도 표시되지 않습니다 .

실제로 if를 입력하여이 논증에 대한 구체적인 도움을 얻으려고한다면 다음과 docker -t --help같이 모호한 답변을 얻을 수 있습니다.

제공되었지만 정의되지 않은 플래그 : -t

따라서이 논쟁에 대해 혼란스러워한다고 비난받을 수 없습니다!

Docker 온라인 문서에는 "의사 tty 할당"이라고 언급되어 있으며 종종 다음과 함께 사용됩니다 -i.

https://docs.docker.com/reference/run/

훌륭한 jwilder/nginx-proxy도커 컨테이너 의 문서 에서 다음과 같은 방식으로 사용되는 것을 보았습니다 .

docker run -d -p 80:80 --name nginx -v /tmp/nginx:/etc/nginx/conf.d -t nginx

이 경우 출력은이 docker 컨테이너 내의 'virtual'tty (Bash 명령 프롬프트 / 터미널)로 출력됩니다. 그런 다음 고정 표시기의 명령을 실행하여이 출력을 볼 수있는 이 컨테이너의 ID 문자의 첫 번째 커플입니다. 이 컨테이너 ID는 다음을 입력하여 찾을 수 있습니다docker logs CONTAINERCONTAINERdocker ps -a

-t다음 링크 에서이 주장을 간략하게 언급했습니다.

-t-i플래그는 의사 청각 장애를 할당하고 연결되지 않은 경우에도 개방 stdin을 유지한다. 이를 통해 bash 프롬프트가 실행되는 한 기존 VM처럼 컨테이너를 사용할 수 있습니다.

https://coreos.com/os/docs/latest/getting-started-with-docker.html

이게 도움이 되길 바란다! 왜 이것이 문서화되거나 많이 사용되지 않는지 잘 모르겠습니다. 실험적이며 향후 버전에서 문서화 된 기능으로 구현 될 수 있습니다.


21
최대 문서 쇼 docker run --help되지는 docker -t --help: -t, --tty=false Allocate a pseudo-TTY"
bskaggs

5

내가 아는 -t것은 다음과 같습니다.

docker exec -ti CONTAINER bash-컨테이너에 "로그인"할 수 있습니다. 그것은 ssh-ing 느낌입니다 (그렇지 않습니다).

그러나 문제는 데이터베이스를 복원하고 싶을 때였습니다.

일반적으로 나는 docker exec -ti mysql.5.7 mysql컨테이너에서 mysql 명령을 실행하고 대화식 터미널을 얻는다.

<dump.sqlDB를 복원 할 수 있도록 이전 명령에 추가 했습니다. 그러나 실패했습니다 cannot enable tty mode on non tty input.

-t도움을 제거 . 여전히 이유를 이해하지 못합니다.

docker exec -i mysql.5.7 mysql < dump.sql

마지막이 작동합니다. 이것이 사람들을 돕기를 바랍니다.


도커 내에서 tty를 시작할 수 있습니까? 작동하지 않는 앱이 있습니다. 도커를 실행하지 않지만 -t프로덕션에서 docker start 명령을 수정할 수 없습니다. 따라서 앱이로 시작되었다고 생각하도록해야합니다 -t.
mvorisek 2016 년

1

Linux에서 명령을 실행할 때 명령을 실행하려면 터미널 (tty)이 필요합니다.

따라서 도커에 연결하거나 도커 컨테이너에서 명령을 실행하려면 도커 컨테이너 내부의 터미널을 고려한 -t 옵션을 제공해야합니다.


0

모든 프로세스에는 세 개의 데이터 스트림이 STDIN/ STDOUT/ STDERR있습니다. 프로세스가 컨테이너에서 실행중인 경우 기본적으로 터미널은 컨테이너에서 실행중인 프로세스의 STDOUT 스트림에 연결됩니다. 따라서 docker run터미널에서 명령 을 실행하는 동안 모든 출력 스트림이 표시됩니다 . 그러나 컨테이너에서 실행중인 프로세스에 입력을 제공하려면 기본적으로 있지 않고 docker run -i명령 으로 수행되는 프로세스의 STDIN 채널에 연결해야합니다 .

-t 대화 형 / 포맷 된 입력 작업에 사용됩니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.