programing

도커 파일 CMD 내의 변수를 사용하려면 어떻게 해야 합니까?

mytipbox 2023. 8. 26. 16:20
반응형

도커 파일 CMD 내의 변수를 사용하려면 어떻게 해야 합니까?

도커 파일 내부:

ENV PROJECTNAME mytestwebsite
CMD ["django-admin", "startproject", "$PROJECTNAME"]

오류:

CommandError: '$PROJECTNAME' is not a valid project name

여기서 가장 빠른 해결책은 무엇입니까?도커는 도커의 이후 버전에서 이 기능을 "수정"하거나 도입할 계획이 있습니까?

참고: Docker 파일에서 CMD 라인을 제거한 다음 Docker 컨테이너를 실행하면 컨테이너 내부에서 Django-admin start project $PROJECTNAME을 수동으로 실행할 수 있으며 프로젝트가 생성됩니다...

실행 목록을 사용하는 경우, 예를 들어...

CMD ["django-admin", "startproject", "$PROJECTNAME"]

...그러면 도커가 셸 없이 지정된 명령을 직접 실행합니다.관련된 셸이 없으므로 다음을 의미합니다.

  • 가변 확장 없음
  • 와일드카드 확장 없음
  • I/O 리디렉션 없음>,<,|,기타
  • 다중 명령 없음command1; command2
  • 등등.

당신이 원한다면 당신의CMD변수를 확장하려면 셸을 준비해야 합니다.다음과 같이 할 수 있습니다.

CMD ["sh", "-c", "django-admin startproject $PROJECTNAME"]

또는 실행 목록 대신 간단한 문자열을 사용하면 이전 예제와 거의 동일한 결과를 얻을 수 있습니다.

CMD django-admin startproject $PROJECTNAME

런타임에 값을 사용하려면 다음을 설정합니다.ENV에 있어서의 가치.Dockerfile빌드 시 사용하려면 다음을 사용해야 합니다.ARG.

예:

ARG value
ENV envValue=$value
CMD ["sh", "-c", "java -jar ${envValue}.jar"]

build 명령에 값을 전달합니다.

docker build -t tagName --build-arg value="jarName"

사용할 수도 있습니다.exec이것은 신호를 처리하고 동시에 변수를 사용하는 유일한 알려진 방법입니다.Dockergithub에 따르면 정상 종료와 같은 것을 구현하려고 시도하는 동안 도움이 될 수 있습니다.

예:

ENV PROJECTNAME mytestwebsite 
CMD exec django-admin startproject $PROJECTNAME

컨테이너 내부에서 Java 프로세스를 시작하려고 합니다.

도커 파일 추출 예제:

ENV JAVA_OPTS -XX +UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1 -XshowSettings:vm 
... 
ENTRYPOINT ["/sbin/tini", "--", "entrypoint.sh"] 
CMD ["java", "${JAVA_OPTS}", "-myargument=true"]

진입점의 예입니다.sh 발췌:

#!/bin/sh 
... 
echo "*** Startup $0 suceeded now starting service using eval to expand CMD variables ***"
exec su-exec mytechuser $(eval echo "$@")

Java 개발자의 경우 아래의 솔루션에 따라 작동합니다.

아래와 같은 도커 파일로 컨테이너를 실행하려고 하면

ENTRYPOINT ["/docker-entrypoint.sh"]
# does not matter your parameter $JAVA_OPTS wrapped as ${JAVA_OPTS}
CMD ["java", "$JAVA_OPTS", "-javaagent:/opt/newrelic/newrelic.jar", "-server", "-jar", "app.jar"]

아래의 엔트리 포인트 셸 스크립트를 사용합니다.

#!/bin/bash
set -e
source /work-dir/env.sh
exec "$@"

이미지는 올바르게 빌드되지만 컨테이너 실행 중에 아래 오류가 인쇄됩니다.

Error: Could not find or load main class $JAVA_OPTS
Caused by: java.lang.ClassNotFoundException: $JAVA_OPTS

대신 Java는 명령줄을 통해 또는 _JAVA_OPTIONS 환경 변수를 통해 명령줄 매개 변수를 읽을 수 있습니다.즉, Docker 파일에서 아무것도 변경하지 않고 _JAVA_OPTIONS를 통해 원하는 명령줄 매개 변수를 전달할 수 있으며 Docker 파일이 유효한 Docker 신호화를 위해 컨테이너의 상위 프로세스로 시작할 수 있도록 합니다.exec "$@".

아래는 저의 최종 버전입니다.Dockerfile그리고.docker-entrypoint.sh삭제된 파일:

...
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["java", "-server", "-jar", "app.jar"]
#!/bin/bash
set -e
source /work-dir/env.sh
export _JAVA_OPTIONS="-XX:+PrintFlagsFinal"
exec "$@"

도커 이미지를 구축하고 실행을 시도하면 아래 로그가 표시됩니다. 이는 제대로 작동했음을 의미합니다.

Picked up _JAVA_OPTIONS: -XX:+PrintFlagsFinal
[Global flags]
      int ActiveProcessorCount                     = -1                                        {product} {default}

위에서 영감을 받아 저는 다음과 같이 했습니다.

#snapshot by default. 1 is release.
ENV isTagAndRelease=0

CMD     echo is_tag: ${isTagAndRelease} && \
        if [ ${isTagAndRelease} -eq 1 ]; then echo "release build"; mvn -B release:clean release:prepare release:perform; fi && \
        if [ ${isTagAndRelease} -ne 1 ]; then echo "snapshot build"; mvn clean install; fi && \ 
       .....

언급URL : https://stackoverflow.com/questions/40454470/how-can-i-use-a-variable-inside-a-dockerfile-cmd

반응형