다른 조건이 있는 경우 도커 파일(외부 인수 포함)
도커 파일이 있습니다.
FROM centos:7
ENV foo=42
그 다음에 짓습니다.
docker build -t my_docker .
실행합니다.
docker run -it -d my_docker
명령줄에서 인수를 전달하여 도커 파일에서 if와 함께 사용할 수 있습니까?제 말은 마치
FROM centos:7
if (my_arg==42)
{ENV=TRUE}
else:
{ENV=FALSE}
이 논쟁으로 구축합니다.
docker build -t my_docker . --my_arg=42
깨끗해 보이지는 않지만 다음과 같이 도커 파일(조건부)을 가질 수 있습니다.
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=45
아니면
docker build -t my_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}"
도커 파일에 대한 설명:
우리는 먼저 A를 받습니다.base
centos:7
당신의 경우), 그리고 그것을 그것만의 단계로 집어넣습니다.base
무대는 조건 전에 하고 싶은 것들을 포함해야 합니다.그 며,다,두가 더 .branch-version-1
그리고.branch-version-2
. 우리가 둘 다 짓는다니까요.final
보다,합니다에 을 둔 이 중 하는 단계.my_arg
도커 조건부 도커 파일입니다.여기 있습니다.
실행 시 출력:
(이것을 조금 줄여서...)
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_arg==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
이 놀라운 아이디어를 주신 티 õ니스 씨께 감사드립니다!
가능한 경우 다른 답변에 설명된 빌드 아르그를 사용하지 마십시오.이것은 오래된 지저분한 해결책입니다.이 문제는 도커의 대상 속성에서 해결합니다.
대상 예제
도커파일
FROM foo as base
RUN ...
# Build dev image
FROM base as image-dev
RUN ...
COPY ...
# Build prod image
FROM base as image-prod
RUN ...
COPY ...
docker build --target image-dev -t foo .
version: '3.4'
services:
dev:
build:
context: .
dockerfile: Dockerfile
target: image-dev
리얼 월드
실제 세계에서는 도커 파일이 복잡해집니다. &용 & COPY --from
보다 빠르고 유지보수가 가능한 Docker 파일:
- 도커는 상속 여부에 관계없이 대상 위의 모든 단계를 구축합니다.빌드킷을 사용하여 상속된 스테이지만 빌드합니다.도커는 v19+까지 해야 합니다.이것이 곧 기본 기능이 되기를 바랍니다.
- 대상이 빌드 단계를 공유할 수 있습니다. 사용
COPY --from
상속을 간소화할 수 있습니다.
FROM foo as base
RUN ...
WORKDIR /opt/my-proj
FROM base as npm-ci-dev
# invalidate cache
COPY --chown=www-data:www-data ./package.json /opt/my-proj/package.json
COPY --chown=www-data:www-data ./package-lock.json /opt/my-proj/package-lock.json
RUN npm ci
FROM base as npm-ci-prod
# invalidate cache
COPY --chown=www-data:www-data ./package.json /opt/my-proj/package.json
COPY --chown=www-data:www-data ./package-lock.json /opt/my-proj/package-lock.json
RUN npm ci --only=prod
FROM base as proj-files
COPY --chown=www-data:www-data ./ /opt/my-proj
FROM base as image-dev
# Will mount, not copy in dev environment
RUN ...
FROM base as image-ci
COPY --from=npm-ci-dev /opt/my-proj .
COPY --from=proj-files /opt/my-proj .
RUN ...
FROM base as image-stage
COPY --from=npm-ci-prod /opt/my-proj .
COPY --from=proj-files /opt/my-proj .
RUN ...
FROM base as image-prod
COPY --from=npm-ci-prod /opt/my-proj .
COPY --from=proj-files /opt/my-proj .
RUN ...
실험 모드를 활성화합니다.
sudo echo '{"experimental": true}' | sudo tee /etc/docker/daemon.json
빌드킷이 활성화된 상태에서 빌드합니다. -드에서 - 로 설정--build-arg BUILDKIT_INLINE_CACHE=1
CI 빌드 작업.
DOCKER_BUILDKIT=1 \
docker build \
--build-arg BUILDKIT_INLINE_CACHE=1 \
--target image-ci\
-t foo:ci
.
과 같이 --cache-from
Prod build 작업
docker pull foo:ci
docker pull foo:stage
DOCKER_BUILDKIT=1 \
docker build \
--cache-from foo:ci,foo:stage \
--target image-prod \
-t prod
.
어떤 이유에서인지 대부분의 답변이 도움이 되지 않았습니다(도커 파일의 FROM 이미지와 관련이 있을 수 있음).
저는 했습니다.bash script
에서와 된 제 입니다.--build-arg
있는지 문을 if 문을 하려면, if안
배시 스크립트:
#!/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
도커 파일:
FROM ...
....
ARG arg
COPY bash.sh /tmp/
RUN chmod u+x /tmp/bash.sh && /tmp/bash.sh $arg
....
도커 빌드:
docker build --pull -f "Dockerfile" -t $SERVICE_NAME --build-arg arg="yes" .
비고: 이것은 배시 스크립트의 다른 것(거짓)으로 갈 것입니다.
docker build --pull -f "Dockerfile" -t $SERVICE_NAME .
비고: if(true)로 이동합니다.
편집 1:
몇번의 시도 끝에 저는 다음의 기사와 이 기사를 발견했습니다. 두가지를 이해하는데 도움이 된 기사입니다.
1) ARG FROM이 빌드 외부에 있기 전의 ARG
2) 기본 셸은 /bin/sh이며, 이는 if가 도커 빌드에서 조금 다르게 작동하고 있음을 의미합니다.예를 들어 문자열을 비교하려면 "==" 대신 "=" 하나만 필요합니다.
죠 할 수 있습니다.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 .
승인된 답변을 통해 질문이 해결될 수도 있지만, 만약 당신이 멀티라인을 원한다면if
건,다를 할 수 .\
(쉘 각 각을 함)합니다.;
. 당신은 심지어 다음과 같은 것을 정의할 수 있습니다.set -eux
첫번째 명령으로
예:
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
이것을 하려면 "test" 이진법을 직접 사용하면 됩니다.또한 "다른" 조건을 지정하지 않으려면 noop 명령 ":"을 사용하여 도커가 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" && :
명령어에 대한 문서에 따르면 이라는 매개 변수가 있습니다.
사용 예시:
docker build --build-arg HTTP_PROXY=http://10.20.30.2:1234 .
IMO 그것이 당신에게 필요한 것입니다 :)
다른 사람들이 말한 것처럼 셸 스크립트가 도움이 될 것입니다.
단지 추가적인 사례일 뿐입니다. IMHO는 (여기서 우연히 발견하여 더 쉬운 사례를 찾고 있는 다른 사람에게) 환경 교체에 대해 언급할 가치가 있습니다.
환경 변수(와 함께 선언됨)
ENV
가 특정 에 의해 .다.Dockerfile
.
${variable_name}
몇 표준 준 bash합니다.
${variable:-word}
다인 경우를 .variable
가 설정되면 결과는 해당 값이 됩니다. 만약variable
설정되어 있지 않습니다.word
결과가 될 것입니다.
${variable:+word}
다인 경우를 .variable
다음에 설정됩니다.word
결과가 됩니다. 그렇지 않으면 결과는 빈 문자열입니다.
Bash 스크립트 및 Alpine/Centos 사용
도커파일
FROM alpine #just change this to centos
ARG MYARG=""
ENV E_MYARG=$MYARG
ADD . /tmp
RUN chmod +x /tmp/script.sh && /tmp/script.sh
script.sh
#!/usr/bin/env sh
if [ -z "$E_MYARG" ]; then
echo "NO PARAM PASSED"
else
echo $E_MYARG
fi
인수 전달: docker build -t test --build-arg MYARG="this is a test" .
....
Step 5/5 : RUN chmod +x /tmp/script.sh && /tmp/script.sh
---> Running in 10b0e07e33fc
this is a test
Removing intermediate container 10b0e07e33fc
---> f6f085ffb284
Successfully built f6f085ffb284
arg 없음: docker build -t test .
....
Step 5/5 : RUN chmod +x /tmp/script.sh && /tmp/script.sh
---> Running in b89210b0cac0
NO PARAM PASSED
Removing intermediate container b89210b0cac0
....
Windows 기반 이미지를 구축하려는 사용자의 경우 다음과 같은 인수에 액세스해야 합니다.%%
# Dockerfile Windows
# ...
ARG SAMPLE_ARG
RUN if %SAMPLE_ARG% == hello_world ( `
echo hehe %SAMPLE_ARG% `
) else ( `
echo haha %SAMPLE_ARG% `
)
# ...
그건 그렇고.ARG
다 .FROM
그렇지 할 수 .
# The ARGs in front of FROM is for image
ARG IMLABEL=xxxx \
IMVERS=x.x
FROM ${IMLABEL}:${IMVERS}
# The ARGs after FROM is for parameters to be used in the script
ARG condition-x
RUN if [ "$condition-x" = "condition-1" ]; then \
echo "$condition-1"; \
elif [ "$condition-x" = "condition-1" ]; then \
echo "$condition-2"; \
else
echo "$condition-others"; \
fi
build -t --build-arg IMLABEL --build-arg IMVERS --build-arg condition-x -f Dockerfile -t image:version .
컨테이너에 프록시 서버를 설정하는 것과 비슷한 문제가 있었습니다.
제가 사용하고 있는 솔루션은 엔트리 포인트 스크립트와 환경 변수 구성을 위한 또 다른 스크립트입니다.RUN을 사용하면 구성 스크립트가 빌드에서 실행되고 컨테이너를 실행할 때 ENTERPOINT가 실행됩니다.
--build-arg는 명령줄에서 프록시 사용자 및 암호를 설정하는 데 사용됩니다.
컨테이너 시작 시 동일한 환경 변수가 필요하기 때문에 파일을 사용하여 빌드부터 실행까지 "지속"했습니다.
진입점 스크립트는 다음과 같습니다.
#!/bin/bash
# Load the script of environment variables
. /root/configproxy.sh
# Run the main container command
exec "$@"
configproxy.sh
#!/bin/bash
function start_config {
read u p < /root/proxy_credentials
export HTTP_PROXY=http://$u:$p@proxy.com:8080
export HTTPS_PROXY=https://$u:$p@proxy.com:8080
/bin/cat <<EOF > /etc/apt/apt.conf
Acquire::http::proxy "http://$u:$p@proxy.com:8080";
Acquire::https::proxy "https://$u:$p@proxy.com:8080";
EOF
}
if [ -s "/root/proxy_credentials" ]
then
start_config
fi
그리고 Docker 파일에서 다음을 구성합니다.
# Base Image
FROM ubuntu:18.04
ARG user
ARG pass
USER root
# -z the length of STRING is zero
# [] are an alias for test command
# if $user is not empty, write credentials file
RUN if [ ! -z "$user" ]; then echo "${user} ${pass}">/root/proxy_credentials ; fi
#copy bash scripts
COPY configproxy.sh /root
COPY startup.sh .
RUN ["/bin/bash", "-c", ". /root/configproxy.sh"]
# Install dependencies and tools
#RUN apt-get update -y && \
# apt-get install -yqq --no-install-recommends \
# vim iputils-ping
ENTRYPOINT ["./startup.sh"]
CMD ["sh", "-c", "bash"]
프록시 설정 없이 빌드
docker build -t img01 -f Dockerfile .
프록시 설정으로 빌드
docker build -t img01 --build-arg user=<USER> --build-arg pass=<PASS> -f Dockerfile .
여기 좀 보세요.
간단한 체크만 추가하면 됩니다.
RUN [ -z "$ARG" ] \
&& echo "ARG argument not provided." \
&& exit 1 || exit 0
가능한 해결책을 많이 보았지만, 오늘 제가 직면한 문제에 적합한 사람은 아무도 없습니다.그래서, 저는 제게 효과가 있었던 또 다른 가능한 해결책을 가지고 질문에 답하는 시간을 갖고 있습니다.
내 경우에는 잘 알려진 것을 이용했습니다.if [ "$VAR" == "this" ]; then echo "do that"; fi
. 주의할 점은, 도커가 왜 이 사건에 대한 이중 평등을 좋아하지 않는지 설명할 수 없습니다.그래서 이렇게 써야 돼요.if [ "$VAR" = "this" ]; then echo "do that"; fi
.
제 경우에 효과가 있었던 완전한 예가 있습니다.
FROM node:16
# Let's set args and envs
ARG APP_ENV="dev"
ARG NPM_CMD="install"
ARG USER="nodeuser"
ARG PORT=8080
ENV NPM_CONFIG_PREFIX=/home/node/.npm-global
ENV PATH=$PATH:/home/node/.npm-global/bin
ENV NODE_ENV=${APP_ENV}
# Let's set the starting point
WORKDIR /app
# Let's build a cache
COPY package*.json .
RUN date \
# If the environment is production or staging, omit dev packages
# If any other environment, install dev packages
&& if [ "$APP_ENV" = "production" ]; then NPM_CMD="ci --omit=dev"; fi \
&& if [ "$APP_ENV" = "staging" ]; then NPM_CMD="ci --omit=dev"; fi \
&& npm ${NPM_CMD} \
&& usermod -d /app -l ${USER} node
# Let's add the App
COPY . .
# Let's expose the App port
EXPOSE ${PORT}
# Let's set the user
USER ${USER}
# Let's set the start App command
CMD [ "node", "server.js" ]
따라서 사용자가 적절한 빌드 인수를 통과하면docker build
command는 제작을 위한 app의 이미지를 만듭니다.그렇지 않으면 devNode.js 패키지로 앱 이미지를 만듭니다.
작동하려면 다음과 같이 전화를 걸 수 있습니다.
# docker build --build-arg APP_ENV=production -t app-node .
저는 파이썬과 같은 구문을 기반으로 도커 파일 생성을 위한 저만의 프레임워크를 작성하게 되었습니다.
이제 오픈 소스가 되었으니 여기서 시도해 보세요: https://github.com/gkpln3/sand
당신의 글을 쓰셔도 됩니다.Sandfile
다음과 같이:
# Sandfile
from sand import *
From("ubuntu", Tag="20.04")
Run([
"apt-get update",
"apt-get install ffmpeg python3"
])
# Install python debugger on debug images.
if config.DEBUG:
Run("pip3 install pdb")
Copy("app", "/app")
Entrypoint("python3 /app/app.py")
그리고 이것으로 전환될 것입니다.
# Auto-generated by Sand, do not edit!
FROM ubuntu:20.04
RUN apt-get update
RUN apt-get install ffmpeg python3
RUN pip3 install pdb
COPY app /app
ENTRYPOINT python3 /app/app.py
를 할 수 .-D
아니면--set
깃발을 올리다
$ sand config -DDEBUG=True
또는 YAML 파일을 사용합니다.
# sand.yaml
DEBUG: True
$ sand config --values sand.yaml
언급URL : https://stackoverflow.com/questions/43654656/dockerfile-if-else-condition-with-external-arguments
'source' 카테고리의 다른 글
xlib으로 스크린샷을 제대로 찍는 방법은? (0) | 2023.10.08 |
---|---|
jQuery로 전화번호 서식 지정하는 방법 (0) | 2023.10.08 |
Oracle Session이란? (0) | 2023.10.08 |
ACF의 관련 게시물 수를 계산합니다. (0) | 2023.10.03 |
까다로운 쿼츠.NET 시나리오 (0) | 2023.10.03 |