셸 스크립트를 사용하여 도커 컨테이너 내에서 스크립트 실행


85

도커 컨테이너를 설정하기위한 셸 스크립트를 만들려고합니다. 내 스크립트 파일은 다음과 같습니다.

#!bin/bash

docker run -t -i -p 5902:5902 --name "mycontainer" --privileged myImage:new /bin/bash

이 스크립트 파일을 실행하면 새로 호출 된 bash에서 컨테이너가 실행됩니다.

이제 위의 셸 스크립트에서 이미 컨테이너 내에있는 스크립트 파일 (test.sh)을 실행해야합니다 (예 : cd /path/to/test.sh && ./test.sh) 어떻게하나요?


1
왜 사용하지 WORKDIRCMD?
Dharmit

1
여기서 --privileged를 사용하고 싶지 않을 것입니다. 참조 : stackoverflow.com/questions/36425230/…
CMP

답변:


121

다음을 사용하여 실행중인 컨테이너에서 명령을 실행할 수 있습니다 docker exec [OPTIONS] CONTAINER COMMAND [ARG...].

docker exec mycontainer /path/to/test.sh

그리고 bash 세션에서 실행하려면 :

docker exec -it mycontainer /bin/bash

거기에서 스크립트를 실행할 수 있습니다.


6
먼저 / bin / bash에 입력 한 다음 해당 bash 내에서 명령을 실행해야하는 경우 어떻게해야합니까?
활발한

44
호스트에서 직접 로컬 스크립트를 실행할 수도 있습니다. docker exec -i mycontainer bash < mylocal.sh 이렇게하면 로컬 호스트 스크립트를 읽고 컨테이너 내에서 실행합니다. 다른 것들 (타르로 파이프 된 .tgz 파일과 같은)로 이것을 할 수 있습니다-단지 '-i'를 사용하여 컨테이너 프로세스 표준 입력으로 파이프합니다.
Marvin

@Marvin PowerShell에서 동등한 것은 무엇입니까? "<"문자는 인식되지 않습니다.
Nicekiwi

1
나는 powershell 전문가가 아니지만 (고맙게도) 주위를 돌아 다니며 stackoverflow.com/a/11788475/500902를 찾았습니다 . 그래서 아마도 Get-Content mylocal.sh | docker exec -i mycontainer bash. 그래도 작동하는지 모르겠습니다.
Marvin

97

Docker 컨테이너가 실행 중이라고 가정하면 다음과 같이 명령을 실행할 수 있습니다.

docker exec mycontainer /bin/sh -c "cmd1;cmd2;...;cmdn"

2
나는이 대답을 좋아한다. 명령 또는 명령 집합을 실행하기 위해 도커 컨테이너에 로그인 할 필요가 없습니다. 감사합니다!
Hatem Jaber

한 단계 더 나아가 전체 명령 ( /bin/sh -c "cmd1; cmd2; ...; cmdn")을 쉘 변수의 값으로 전달하는 방법을 알고 있습니까? 'docker run'은 인용 된 문자열이 아닌 단일 명령과 인용되지 않은 개별 인수를 기대하는 것처럼 보이기 때문에 묻습니다.
davidA

@meowsqueak :이 답변은 이미 생성되고 실행중인 컨테이너에서 해당 컨테이너에 로그인하지 않고 여러 명령을 실행하는 방법을 알려줍니다. 이는 자동화에 도움이됩니다. 그러나 컨테이너 생성시 여러 명령을 실행하려는 경우 (PS : docker run 명령이 컨테이너를 생성하고 시작 함) 동일한 스레드 stackoverflow.com/a/41363989/777617
Cyclops

대신에 cmd1전체 for 루프를 전달해야하지만 루프 문과 do;다음에 예상 됩니다. 전체 for-loop를 단일 명령으로 어떻게 실행할 수 있습니까? 가능할까요? cmd1
Nicholas K

18

이 질문에 대한 답변을 찾고 있었고 Dockerfile 솔루션 에서 ENTRYPOINT를 찾았 습니다.

Dockerfile

...
ENTRYPOINT /my-script.sh ; /my-script2.sh ; /bin/bash

이제 컨테이너를 시작할 때 스크립트가 실행되고 스크립트가 실행 된 후 bash 프롬프트가 표시됩니다.


6

Docker 이미지에 로컬 디렉토리를 마운트하고 .bashrc. 스크립트가 모든 새 셸에서 실행되기를 원하지 않는 한 스크립트가 함수로 구성되어야한다는 것을 잊지 마십시오. (이는 업데이트 공지를 참조하십시오.)

이 솔루션을 사용하여 도커 인스턴스 외부의 스크립트를 업데이트 할 수 있습니다. 이렇게하면 변경 사항이 발생해도 이미지를 다시 실행할 필요없이 새 셸을 엽니 다. (셸 다시 열기 제거-업데이트 알림 참조)

현재 디렉터리를 바인딩하는 방법은 다음과 같습니다.

docker run -it -v $PWD:/scripts $my_docker_build /bin/bash

이제 현재 디렉터리가 /scriptsDocker 인스턴스에 바인딩됩니다 .

(오래됨) .bashrc변경 사항 을 저장하려면 다음 명령을 사용하여 작업 이미지를 커밋합니다.

docker commit $container_id $my_docker_build

최신 정보

모든 변경 사항에 대해 새 셸을 여는 문제를 해결하기 위해 이제 다음을 수행합니다.

dockerfile 자체에 RUN echo "/scripts/bashrc" > /root/.bashrc". 내부 zshrc에서 스크립트 디렉토리를 경로로 내 보냅니다. 이제 스크립트 디렉토리에 하나가 아닌 여러 파일이 포함됩니다. 이제 모든 변경 사항에 대해 하위 셸을 열지 않고도 모든 스크립트를 직접 호출 할 수 있습니다.

BTW 컨테이너 외부에서도 히스토리 파일을 정의 할 수 있습니다. 이렇게하면 더 이상 bash 변경을 커밋 할 필요가 없습니다.


너무 늦었 어 ..! @javier는 이미 직접적인 솔루션을 보여줍니다! 나는 하나가 여전히 낫다고 느낍니다.
zappy

2
@zappy javier의 솔루션은 나를 위해이 문제를 편리하게 해결하지 못했지만 내 솔루션은 비슷한 문제가있는 사람들이 도커 이미지를 다시 시작하고 싶지 않은 사람들에게 흥미로울 것이라고 생각했습니다. 필요한 기능을 볼 수 있습니다. 예를 들어 한 번에 여러 개의 Docker 이미지를 사용하여 개발 클러스터를 가동하는 경우 항상 다시 시작하고 싶지는 않습니다.
Devpool

3

실행중인 컨테이너를 원하지 않거나 갖고 있지 않은 경우 run명령을 사용 하여 스크립트를 직접 호출 할 수 있습니다 .

반복 tty -i -t인수를 제거 하고 다음을 사용하십시오.

    $ docker run ubuntu:bionic /bin/bash /path/to/script.sh

이것은 다른 스크립트에서도 작동합니다 (테스트하지 않음).

    $ docker run ubuntu:bionic /usr/bin/python /path/to/script.py


0

여러 인스턴스에서 동일한 명령을 실행하려면 다음을 수행하십시오.

for i in c1 dm1 dm2 ds1 ds2 gtm_m gtm_sl; do docker exec -it $i /bin/bash -c "service sshd start"; done
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.