docker run을 통해 셸 스크립트에 인수를 전달하는 방법


132

나는 도커 세계에 처음이다. 도커 컨테이너를 통해 명령 줄 인수를 취하는 쉘 스크립트를 호출해야합니다. 예 : 내 셸 스크립트는 다음과 같습니다.

#!bin/bash
echo $1

Dockerfile은 다음과 같습니다.

FROM ubuntu:14.04
COPY ./file.sh /
CMD /bin/bash file.sh

컨테이너를 실행하는 동안 인수를 전달하는 방법을 잘 모르겠습니다

답변:


61

같은 것을 사용하십시오 file.sh

#!/bin/bash
echo $1

기존 Dockerfile을 사용하여 이미지를 빌드하십시오.

docker build -t test .

인수 abc또는 xyz다른 것으로 이미지를 실행하십시오 .

docker run -ti test /file.sh abc

docker run -ti test /file.sh xyz

27
최종 사용자가 file.sh에 대해 직접 알지 못하게하려면 ENTRYPOINT가 좋은 방법이라고 생각합니다.
greg.kindel

어떻게 이런 스크립트를 시작할 수 있습니까 docker run -ti test /file.sh abc? 스크립트가 반드시 실행되어야한다고 생각 docker run -ti test sh /file.sh abc합니다. sh 또는 / bin / sh가 올바르게 실행됩니다.
Vamsidhar Muggulla

1
다른 사람은 여기에 오십시오. / usr / bin / env 트릭은 선택적인 스타일 환경 설정이며 이것이 작동하도록 요구하지는 않습니다. 또한 #! line은 구매 기본값을 사용할 통역사를 나타냅니다. 따라서 스크립트를 호출하여 실행할 수 있습니다.
어디에서 왔습니까?

165

이 스크립트로 file.sh

#!/bin/bash
echo Your container args are: "$@"

Dockerfile

FROM ubuntu:14.04
COPY ./file.sh /
ENTRYPOINT ["/file.sh"]

당신은 할 수 있어야합니다 :

% docker build -t test .
% docker run test hello world
Your container args are: hello world

9
"/file.sh"주위의 ""를 잊어 버린 경우 작동하지 않습니다.
kev

6
어떤 이유로, 이것은 작동하지 않습니다ENTRYPOINT ./file.sh
phil294

6
chmod +x file.sh실행 플래그를 설정하는 것을 잊지 마십시오 .
topskip

1
@kev, 왜 그런지 아십니까? 차이 무엇 ["/file.sh"]/file.sh또는[/file.sh]
Nitzankin

1
@Nitzankin은 왜 올바른 json 형식이 필요한지에 대한 대답을 봅니다.
BMitch

60

Docker를 사용하면 이러한 종류의 정보를 전달하는 올바른 방법은 환경 변수를 통하는 것입니다.

따라서 동일한 Dockerfile을 사용하여 스크립트를

#!/bin/bash
echo $FOO

빌드 후 다음 docker 명령을 사용하십시오.

docker run -e FOO="hello world!" test

20
이것이 왜 가장 높은 투표 응답입니까? 환경 변수는 정보를 전달하는 또 다른 방법이지만 OP가 요구하는 것은 아닙니다. 물론 컨테이너에 인수를 전달하려는 OP의 욕구에 대해 부적절한 것은 없습니다.
부분적으로 흐린

8
@PartlyCloudy 분명히 잘못된 생각에도 불구하고 "적절한"답변을 제공하기 때문에 사람들은 이와 같은 생각을합니다. Docker의 주요 디자인 원칙은 상식보다 교리를 우선시하는 것입니다.
augurar

1
@augurar :이 답변을 개선하기 위해이 답변이 "분명히 잘못되었다"고 생각하는 이유를 설명 할 수 있습니까?
Emil Stenström

2
SO에 대해 많은 XY 문제가 있습니다. OP가 Docker를 처음 사용한다고 언급했기 때문에 목표를 달성하기 위해 권장되는 방법을 보여주는 것이 합리적입니다. 따라서 이것은 큰 대답입니다.
colm.anseo 1

1
빌드 args 및 모든 혼란으로 변수를 전달하는 대신 작업을 수행하는 가장 간단한 방법입니다. 환경 변수로 비밀을 전달하는 데 매우 유용합니다.
Arvind Sridharan 2018 년

32

여기에 상호 작용하는 몇 가지가 있습니다.

  1. docker run your_image arg1 arg2의 값을로 CMD바꿉니다 arg1 arg2. 그것은 더 많은 값을 추가하지 않고 CMD를 완전히 대체합니다. 그렇기 때문에 docker run some_image /bin/bash컨테이너에서 bash 쉘을 실행하는 경우가 종종 있습니다 .

  2. ENTRYPOINT와 CMD 값이 모두 정의되어 있으면 docker는 두 개를 연결하고 연결된 명령을 실행하여 컨테이너를 시작합니다. 따라서 진입 점을로 정의 file.sh하면 이제 args로 전달 될 추가 arg로 컨테이너를 실행할 수 있습니다 file.sh.

  3. docker의 진입 점 및 명령에는 셸을 시작하는 문자열 구문과 exec를 수행하는 json 구문의 두 가지 구문이 있습니다. 셸은 IO 리디렉션, 여러 명령을 함께 연결 (예 :) &&, 변수 대체 등 을 처리하는 데 유용합니다 . 그러나 해당 셸은 신호 처리에 방해가됩니다 (중단하는 데 10 초의 지연이있는 경우) 컨테이너, 이것은 종종 원인이 됨)와 시작점과 명령을 함께 연결합니다. 진입 점을 문자열로 정의하면 실행 /bin/sh -c "file.sh"됩니다. 이것만으로도 충분 합니다. 그러나 문자열로 정의 된 명령이있는 경우 /bin/sh -c "file.sh" /bin/sh -c "arg1 arg2"컨테이너 내부에서 실행되는 명령 과 같은 것이 좋지 않습니다. 이 두 옵션의 상호 작용 방식에 대한 자세한 내용 은 여기 표를 참조하십시오

  4. -c옵션은 단일 인수 만 사용합니다. 그 이후로 모든 것이로 전달받을 것입니다 $1, $2당신은 명시 적으로 인수를 전달하지 않는 한 그 하나의 인자에 있지만 내장 된 쉘 스크립트로, 등. 즉 /bin/sh -c "file.sh $1 $2" "arg1" "arg2", 작동하지만 /bin/sh -c "file.sh" "arg1" "arg2"이후에 file.sh인수없이 호출 되지는 않았습니다 .

이를 종합하면 일반적인 디자인은 다음과 같습니다.

FROM ubuntu:14.04
COPY ./file.sh /
RUN chmod 755 /file.sh
# Note the json syntax on this next line is strict, double quotes, and any syntax
# error will result in a shell being used to run the line.
ENTRYPOINT ["file.sh"]

그리고 나서 다음과 같이 실행하십시오.

docker run your_image arg1 arg2

이에 대한 자세한 내용은 다음과 같습니다.


1
["bash", "--login", "-c"]이미지에 / etc / profile 소스를 가져 오기 위해 시작점을 설정하는 실험을 했지만 나중에 도커 실행에 전달 된 쉘 스크립트로 인수가 전달되지 않는 이유가 궁금해졌습니다. !
Apteryx

23

내가 가진 것은 실제로 물건을 실행하는 스크립트 파일입니다. 이 스크립 파일은 비교적 복잡 할 수 있습니다. "run_container"라고하겠습니다. 이 스크립트는 명령 행에서 인수를 가져옵니다.

run_container p1 p2 p3

간단한 run_container는 다음과 같습니다.

#!/bin/bash
echo "argc = ${#*}"
echo "argv = ${*}"

내가하고 싶은 것은 "dockering"후에 도커 명령 줄의 매개 변수를 사용 하여이 컨테이너를 시작할 수 있기를 원합니다.

docker run image_name p1 p2 p3

매개 변수로 p1 p2 p3을 사용하여 run_container 스크립트를 실행하십시오.

이것은 내 솔루션입니다.

도커 파일 :

FROM docker.io/ubuntu
ADD run_container /
ENTRYPOINT ["/bin/bash", "-c", "/run_container \"$@\"", "--"]

7
ENTRYPOINT배열 의 세 번째 값을 "/run_container \"$@\""공백으로 포함하는 인수는 올바르게 처리됩니다 (예 :) docker run image_name foo 'bar baz' quux.
davidchambers

내 bash 파일에 switch / case 문을 추가하면 ENTRYPOINT [ "run_container.sh"]가 더 이상 작동하지 않지만 ENTRYPOINT [ "sh", "-c", "run_container.sh"]는 더 이상 내 매개 변수를 허용하지 않습니다. 이 솔루션 (@davidchambers 제안 포함)이 저에게 효과적이었습니다.
rhamilton

10

@build time을 실행하려면 :

CMD /bin/bash /file.sh arg1

@run time을 실행하려면 :

ENTRYPOINT ["/bin/bash"]
CMD ["/file.sh", "arg1"]

그런 다음 호스트 셸에서

docker build -t test .
docker run -i -t test

2
ENTRYPOINT내가 런타임을 원한다고 생각하는 OP에게는 좋은 대답이지만 실제로 빌드 시간 변수를 원한다면이 대답은 깨졌습니다. 사용 ARGdocker build --build-arg docs.docker.com/engine/reference/builder/#arg
greg.kindel

0

다른 옵션 ...

이것을 작동 시키려면

docker run -d --rm $IMG_NAME "bash:command1&&command2&&command3"

dockerfile에서

ENTRYPOINT ["/entrypoint.sh"]

entrypoint.sh에서

#!/bin/sh

entrypoint_params=$1
printf "==>[entrypoint.sh] %s\n" "entry_point_param is $entrypoint_params"

PARAM1=$(echo $entrypoint_params | cut -d':' -f1) # output is 1 must be 'bash' it     will be tested    
PARAM2=$(echo $entrypoint_params | cut -d':' -f2) # the real command separated by     &&

printf "==>[entrypoint.sh] %s\n" "PARAM1=$PARAM1"
printf "==>[entrypoint.sh] %s\n" "PARAM2=$PARAM2"

if [ "$PARAM1" = "bash" ];
then
    printf "==>[entrypoint.sh] %s\n" "about to running $PARAM2 command"
    echo $PARAM2 | tr '&&' '\n' | while read cmd; do
        $cmd
    done    
fi

":"가 포함 된 명령은 cut -d ':'의 변경이 필요하고 docker run -d --rm $ IMG_NAME "bash : echo $ PATH"와 같은 명령은 호스트 대신 호스트 경로 값을 표시합니다. 하나
wagnermarques
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.