Docker CMD 지시문의 여러 명령


39

`Dockerfile의 CMD 지시문을 통해 런타임에 두 개의 명령을 실행하려고 할 때 무슨 일이 일어나고 있는지 이해하지 못합니다. 나는 이것이 효과가 있다고 가정했다.

CMD ["/etc/init.d/nullmailer", "start", ";", "/usr/sbin/php5-fpm"]

그러나 작동하지 않습니다. 컨테이너가 시작되지 않았습니다. 그래서 나는 이것을 이렇게해야했다.

CMD ["sh", "-c", "/etc/init.d/nullmailer start ; /usr/sbin/php5-fpm"]

이해가 안 돼요 왜 그런 겁니까? 왜 첫 줄이 옳지 않은가? 누군가 "CMD 쉘 형식 대 JSON 형식 등"을 설명해 줄 수 있습니까? 간단히 말해서.

참고 command:docker-compose.yml, 예상대로의 지시문 과 동일 합니다.

답변:


33

차이점은 두 번째 명령이 셸 처리를 수행하지만 첫 번째 명령은 수행하지 않는 것과 관련이 있다고 생각합니다. 공식 문서 에 따라 execand shell형식이 있으며 첫 번째 명령은 exec 형식이며 예를 들어 환경 변수를 확장하지 않지만 두 번째 명령은 exec 형식입니다. 따라서 exec 양식을 사용하면 명령이 쉘 처리에 의존하여 실패 할 수 있습니다. 당신은 이것을 실행하여 확인할 수 있습니다docker logs CONTAINERID

두 번째 명령 인 쉘 형식은 다음과 같습니다.

CMD /etc/init.d/nullmailer start ; /usr/sbin/php5-fpm

문서에서 발췌-

참고 : 셸 양식과 달리 exec 양식은 명령 셸을 호출하지 않습니다. 이는 정상적인 쉘 처리가 발생하지 않음을 의미합니다. 예를 들어에 대한 CMD [ "echo", "$HOME" ]변수 대체는 수행하지 않습니다 $HOME. 쉘 처리를 원하면 쉘 양식을 사용하거나 쉘을 직접 실행하십시오 (예 :) CMD [ "sh", "-c", "echo", "$HOME" ].


환경 변수로 인해 명령이 실패했을 수 있습니다. exec선호하는 양식이므로이 양식을 계속 사용해야 합니까? 왜 선호됩니까? 아니면 더 간단한 shell형태를 사용해야 합니까?
Vladan

하나의 명령을 차례로 실행하는 것이 쉘 기능이기 때문에 실패했습니다. 환경 변수는 붉은 청어입니다.
Bryan

Docker에서 여러 서비스를 실행하는 경우 감독자와 같은 프로세스 관리자를 사용하는 것이 좋습니다. 그렇게하면 CMD 섹션에서 관리자 만 시작하고 서비스 시작을 처리합니다. 자세한 내용은 docs.docker.com/articles/using_supervisord
Daniel t

이것은 내가 방금 읽은 정확한 기사입니다 :) 감사합니다.
Vladan

나는 왜 당신이 왜해야하는지 이해하지 못합니다 CMD [ "sh", "-c", "echo", "$HOME"]. 왜 CMD ["sh", "-c", "echo $HOME"]또는, 그 문제에 관해서는, CMD ["sh -c echo $HOME"]?
sixty4bit

4

스스로 힘들게하지 마십시오. bash 파일 "start.sh"를 작성하십시오.

#!/bin/bash

/usr/bin/command2 param1
/usr/bin/commnad1

Dockerfile에서 다음을 수행하십시오.

ADD start.sh /

CMD ["/start.sh"]

2

CMD(및 RUNand ENTRYPOINT) 의 json 구문은 인수를 커널에 직접 exec syscall로 전달합니다. exec syscall에서 공백으로 따옴표, 이스케이프 제거, IO 대체, 변수 대체, 명령 사이의 파이프 연결, 여러 명령 실행 등을 통해 인수와 명령을 분리 할 수 ​​없습니다. syscall은 실행 파일을 실행하고 해당 실행 파일에 전달할 인수 목록 만 가져 와서 실행합니다.

문자는 같은 $변수를 확장하기 위해 ;별도의 명령에 별도의 인수로 (공간) &&||체인 명령에, >출력 리디렉션, |같은 쉘과해야 할 일의 모든 기능 명령 사이에 파이프 등이다 /bin/sh또는 /bin/bash해석하고이를 구현하기를.


의 문자열 구문으로 전환하면 CMDdocker는 쉘로 명령을 실행합니다.

CMD /etc/init.d/nullmailer start ; /usr/sbin/php5-fpm

그렇지 않으면 두 번째 구문은 똑같은 작업을 수행합니다.

CMD ["sh", "-c", "/etc/init.d/nullmailer start ; /usr/sbin/php5-fpm"]

첫 번째 명령이 실패한 경우, 특히 백그라운드에서 실행되는 경우 오류 처리가 없으므로 컨테이너 내부에서 여러 가지 명령을 실행하지 않는 것이 좋습니다. 또한 쉘을 컨테이너 내부에 pid 1로 실행하면 신호 처리가 중단되어도 커가 컨테이너를 10 초 지연시키고 부적절하게 죽일 수 있습니다. 쉘 exec명령 을 사용하여 신호 처리를 완화 할 수 있습니다 .

CMD /etc/init.d/nullmailer start ; exec /usr/sbin/php5-fpm

그러나 백그라운드에서 자동으로 실패한 프로세스를 처리하려면 감독자와 같은 일종의 다중 프로세스 관리자로 전환하거나 응용 프로그램을 여러 컨테이너로 분할하고 docker-compose와 같은 방식으로 배포해야합니다.


1

DOCKER CMD 형식에서는 첫 번째 매개 변수 만 실행되고 나머지는이 명령에 공급되기 때문에 첫 번째 명령이 실패한다고 생각합니다.

두 번째 형식은 모든 명령이 ";"으로 분리 되었기 때문에 작동합니다. sh 명령에 입력되어 실행됩니다.


1

"시작"뒤에 세미 쉼표를 넣어야한다고 생각하지 않습니다

사용하는 대신

CMD ["/etc/init.d/nullmailer", "start", ";", "/usr/sbin/php5-fpm"]

시험

CMD ["/etc/init.d/nullmailer", "start", "/usr/sbin/php5-fpm"]

docker가 "sh -c"를 사용하므로 위 명령은 다음과 같이 실행됩니다

/etc/init.d/nullmailer start
/etc/init.d/nullmailer /usr/sbin/php5-fpm

json 구문은 쉘과 함께 명령을 실행하지 않으며 sh -c해당 시나리오 에는 없습니다 .
BMitch
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.