[docker] Dockerfile if else 조건 외부 인수 포함

나는 dockerfile이 있습니다

FROM centos:7
ENV foo=42

그런 다음 그것을 구축

docker build -t my_docker .

그리고 그것을 실행하십시오.

docker run -it -d  my_docker

명령 줄에서 인수를 전달하고 Dockerfile의 다른 경우와 함께 사용할 수 있습니까? 내 말은

FROM centos:7
if (my_arg==42)
     {ENV=TRUE}
else:
     {ENV=FALSE}

이 주장으로 구축하십시오.

 docker build -t my_docker . --my_arg=42



답변

깨끗하게 보이지 않을 수도 있지만 다음과 같이 Dockerfile (조건부)을 가질 수 있습니다.

FROM centos:7
ARG arg
RUN if [ "x$arg" = "x" ] ; then echo Argument not provided ; else echo Argument is $arg ; fi

그런 다음 이미지를 다음과 같이 빌드하십시오.

docker build -t my_docker . --build-arg arg=45

또는

docker build -t my_docker .


답변

어떤 이유로 여기에있는 대부분의 답변이 도움이되지 않았습니다 (Dockerfile의 내 FROM 이미지와 관련이있을 수 있습니다)

그래서 Docker가 인수가 비어 있는지 여부를 확인하여 빌드하는 동안 if 문을 처리하기 위해 bash script내 작업 공간에서 를 만드는 것을 선호했습니다.--build-arg

Bash 스크립트 :

#!/bin/bash -x

if test -z $1 ; then
    echo "The arg is empty"
    ....do something....
else
    echo "The arg is not empty: $1"
    ....do something else....
fi

Dockerfile :

FROM ...
....
ARG arg
COPY bash.sh /tmp/
RUN chmod u+x /tmp/bash.sh && /tmp/bash.sh $arg
....

Docker 빌드 :

docker build --pull -f "Dockerfile" -t $SERVICE_NAME --build-arg arg="yes" .

비고 : 이것은 bash 스크립트의 else (false)로 이동합니다.

docker build --pull -f "Dockerfile" -t $SERVICE_NAME .

비고 : 이것은 if (true)로 이동합니다.

편집 1 :

몇 번을 시도해 후 나는 다음과 같은 발견
두 가지를 이해하는 나에게 도움이 :

1) FROM 이전의 ARG는 빌드 외부에 있습니다.

2) 기본 셸은 / bin / sh입니다. 즉, if else가 도커 빌드에서 약간 다르게 작동 함을 의미합니다. 예를 들어 문자열을 비교하려면 “==”대신 “=”하나만 필요합니다.

그래서 당신은 내부에서 이것을 할 수 있습니다 Dockerfile

ARG argname=false   #default argument when not provided in the --build-arg
RUN if [ "$argname" = "false" ] ; then echo 'false'; else echo 'true'; fi

그리고 docker build:

docker build --pull -f "Dockerfile" --label "service_name=${SERVICE_NAME}" -t $SERVICE_NAME --build-arg argname=true .


답변

명령대한 문서에docker build 따르면 라는 매개 변수가 --build-arg있습니다.

사용 예 :

docker build --build-arg HTTP_PROXY=http://10.20.30.2:1234 .

IMO 그것은 당신이 필요한 것입니다 🙂


답변

제안 된 솔루션에 대한 흥미로운 대안이 있습니다. 단일 Dockerfile 과 함께 작동하고 조건부 빌드 당 docker 빌드에 대한 단일 호출 만 필요 하고 bash를 피 합니다.

해결책:

다음은 Dockerfile그 문제를 해결합니다. 복사하여 붙여넣고 직접 시도해보십시오.

ARG my_arg

FROM centos:7 AS base
RUN echo "do stuff with the centos image"

FROM base AS branch-version-1
RUN echo "this is the stage that sets VAR=TRUE"
ENV VAR=TRUE

FROM base AS branch-version-2
RUN echo "this is the stage that sets VAR=FALSE"
ENV VAR=FALSE

FROM branch-version-${my_arg} AS final
RUN echo "VAR is equal to ${VAR}"

Dockerfile에 대한 설명 :

먼저 base이미지 ( centos:7귀하의 경우)를 가져 와서 자체 단계에 넣습니다. base단계는 조건 전에하고 싶은 일을 포함해야합니다. 그 후, 조건의 분기를 나타내는 두 단계가 더 있습니다 : branch-version-1branch-version-2. 우리는 둘 다 구축합니다. final이 단계의이 선택하는 하나 이상의 단계는 기반 my_arg. 조건부 Dockerfile. 됐습니다.

실행시 출력 :

(약간 줄여서 …)

my_arg==2

docker build --build-arg my_arg=2 .
Step 1/12 : ARG my_arg
Step 2/12 : ARG ENV
Step 3/12 : FROM centos:7 AS base
Step 4/12 : RUN echo "do stuff with the centos image"
do stuff with the centos image
Step 5/12 : FROM base AS branch-version-1
Step 6/12 : RUN echo "this is the stage that sets VAR=TRUE"
this is the stage that sets VAR=TRUE
Step 7/12 : ENV VAR=TRUE
Step 8/12 : FROM base AS branch-version-2
Step 9/12 : RUN echo "this is the stage that sets VAR=FALSE"
this is the stage that sets VAR=FALSE
Step 10/12 : ENV VAR=FALSE
Step 11/12 : FROM branch-version-${my_arg}
Step 12/12 : RUN echo "VAR is equal to ${VAR}"
VAR is equal to FALSE

my_var==1

docker build --build-arg my_arg=1 .
...
Step 11/12 : FROM branch-version-${my_arg}
Step 12/12 : RUN echo "VAR is equal to ${VAR}"
VAR is equal to TRUE

이 놀라운 아이디어에 대해 Tõnis에게 감사드립니다!


답변

이 작업을 수행하려면 “test”바이너리를 직접 사용하십시오. 또한 “else”조건을 지정하지 않으려면 noop 명령 “:”을 사용해야합니다. 따라서 docker는 0이 아닌 반환 값 오류로 중지되지 않습니다.

RUN test -z "$YOURVAR" || echo "var is set" && echo "var is not set"
RUN test -z "$YOURVAR" && echo "var is not set" || :
RUN test -z "$YOURVAR" || echo "var is set" && :


답변

다른 사람들이 말했듯이 쉘 스크립트가 도움이 될 것입니다.

추가 사례 인 IMHO는 언급 할 가치가 있습니다 (여기에서 우연히 발견 한 다른 사람에게 더 쉬운 사례를 찾고 있음), 그것은 환경 교체 입니다.

환경 변수 ( ENV문으로 선언 됨 )는 특정 명령어에서 Dockerfile.

${variable_name}구문은 아래에 지정된 몇 가지 표준 bash 수정 자도 지원합니다.

  • ${variable:-word}variable가 설정되면 결과가 해당 값이 됨을 나타냅니다 . variable이 설정되지 않은 경우 word결과가됩니다.

  • ${variable:+word}variable가 설정 word되면 결과가되고 그렇지 않으면 결과가 빈 문자열 임을 나타냅니다 .


답변

허용 대답은 문제를 해결할 수 있지만, 여러 원하는 경우 ifdockerfile의 조건을, 당신은 배치 할 수 있습니다 \(당신이 쉘 스크립트에서하는 방식과 유사) 각 라인의 끝과 각 명령 끝에서 ;. set -eux첫 번째 명령 과 같이 someting을 정의 할 수도 있습니다 .

예:

RUN set -eux; \
  if [ -f /path/to/file ]; then \
    mv /path/to/file /dest; \
  fi; \
  if [ -d /path/to/dir ]; then \
    mv /path/to/dir /dest; \
  fi

귀하의 경우 :

FROM centos:7
ARG arg
RUN if [ -z "$arg" ] ; then \
    echo Argument not provided; \
  else \
    echo Argument is $arg; \
  fi

그런 다음 다음으로 빌드하십시오.

docker build -t my_docker . --build-arg arg=42