बाहरी तर्कों के साथ यदि अन्य शर्त हो तो डॉकरफाइल


131

मेरे पास डॉकटरफाइल है

FROM centos:7
ENV foo=42

तब मैं इसका निर्माण करता हूं

docker build -t my_docker .

और इसे चलाएं।

docker run -it -d  my_docker

क्या कमांड लाइन से तर्कों को पास करना संभव है और इसका उपयोग डॉकफेराइल में अन्य के साथ किया जा सकता है? मेरा मतलब कुछ ऐसा है

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

और इस तर्क के साथ निर्माण करें।

 docker build -t my_docker . --my_arg=42

1
यह शायद एक निर्माण स्क्रिप्ट से संभाला जाना चाहिए।
स्नोप्स

@ @ЕлЗный जो गलत है। नीचे उत्तर देखें, इसे
devnul3

स्वीकृत उत्तर प्रश्न के भाग "यदि अन्य शर्त" को कवर नहीं करता है। बेहतर होगा कि इसका नाम बदलकर "बाहरी तर्कों के साथ डॉकफाइल" रखा जाए, अगर कंडीशन चेक का मतलब ज़रूरत नहीं है।
रुसलान कबालिन

@RuslanKabalin - स्वीकृत उत्तर में "फिर" और "अन्य" दोनों खंड हैं। एकमात्र अंतर यह है कि "यदि स्थिति" में परीक्षण किया गया है। कोड के लिए प्रश्न में दिखाया गया है: RUN if [ "$arg" == "42" ]; then ENV=TRUE; else ENV=FALSE; fi। या अगर arg गायब हो सकता है: RUN if [ "x$arg" == "x42" ]; then ...
ToolmakerSteve

जवाबों:


193

यह साफ नहीं लग सकता है, लेकिन आप अपने डॉकरफाइल (सशर्त) का पालन कर सकते हैं:

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 .


20
[ "$arg" = "x" ]इसके बजाय नहीं होना चाहिए [ "x$arg" = "x" ]?
क्वान्ट

4
यदि कोई तर्क प्रदान किया जाता है, तो किसी विशेष तर्क के लिए जाँच करने के बजाय, यहाँ त्रिशूल जाँच रहा है। यह अधिक स्पष्ट प्रतीत होता है अगर फिर से लिखा जाए, if [ $arg != "" ] ;लेकिन मुझे यकीन है कि कुछ
गच्चा है

21
if [[ -n "$arg" ]]सच है अगर एक परम खाली नहीं है, if [[ -z "$arg" ]]सच है अगर एक परम खाली है
एक्युमर्टिनी

6
यदि स्टेटमेंट हो तो मल्टीलाइन कैसे लिखें?
आशुतोष चमोली

12
@Quannt - नहीं, शेल स्क्रिप्ट क्यों देखते हैं ...[ "x$arg" = "x" ] ऐसा लगता है कि यह दो उद्धृत स्ट्रिंग्स की तुलना कर रहा है, लेकिन उद्धरण छीन लिए जाते हैं; इससे वाक्य रचना सही रहती है। उद्धरण के बाद अलग करना: अच्छा if x = x ..:। बुरा: if = । फिर भी, पैरामीटर के अस्तित्व की जाँच करने के लिए बेहतर तरीके हैं: इनपुट तर्कों के अस्तित्व की जाँच करें
टूलमेकरसैट

20

किसी कारण से यहाँ अधिकांश उत्तर मेरी मदद नहीं कर पाए (हो सकता है कि यह डॉकरीफाइल में मेरी FROM छवि से संबंधित हो)

इसलिए मैंने bash scriptअपने कार्यक्षेत्र में संयुक्त रूप से बनाना पसंद किया --build-arg, ताकि अगर कथन खाली है या नहीं तो जाँच कर बताएं कि तर्क खाली है या नहीं

बैश स्क्रिप्ट:

#!/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 build --pull -f "Dockerfile" -t $SERVICE_NAME --build-arg arg="yes" .

टिप्पणी: यह बाश स्क्रिप्ट में अन्य (झूठी) पर जाएगी

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

टिप्पणी: यह अगर (सच्चा) जाएगा

1 संपादित करें:

कई प्रयासों के बाद भी मैं निम्नलिखित पाया है लेख और इस एक जो मुझे मदद मिली 2 बातें समझने के लिए:

1) FROM से पहले ARG बिल्ड के बाहर है

2) डिफ़ॉल्ट शेल / बिन / श है जिसका अर्थ है कि यदि डॉक बिल्ड में कुछ अलग काम कर रहा है। उदाहरण के लिए आपको तार की तुलना करने के लिए "==" के बजाय केवल एक "=" की आवश्यकता है।

तो आप अंदर यह कर सकते हैं 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 .


17

प्रस्तावित समाधानों का एक दिलचस्प विकल्प है, जो एक एकल डॉकरफाइल के साथ काम करता है , प्रति सशर्त निर्माण के लिए डॉक बिल्ड बनाने और बैश से बचने के लिए केवल एक कॉल की आवश्यकता होती है ।

उपाय:

निम्नलिखित 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}"

डॉकफाइल की व्याख्या:

हम पहले एक baseछवि प्राप्त करते हैं ( centos:7आपके मामले में) और इसे अपने स्वयं के चरण में डालते हैं। baseचरण चीजें हैं जो आप शर्त से पहले क्या करना चाहते हैं शामिल करना चाहिए। उसके बाद, हमारे पास दो और चरण हैं, जो हमारी स्थिति की शाखाओं का प्रतिनिधित्व करते हैं: branch-version-1और branch-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 को धन्यवाद!


अब तक, सबसे अच्छा तरीका।
फेलिप डेसिडारिटी

बहुत सोचा, यही कारण है कि मैंने इसे यहाँ पोस्ट किया है। ख़बर @FelipeDesiderati
User12547645

1
यह यहां प्रस्तुत सभी का सबसे अच्छा समाधान है, क्योंकि आपको स्क्रिप्ट / बैश के साथ वर्कआर्ड का उपयोग करने की आवश्यकता नहीं है, लेकिन एक ऐसे तरीके का उपयोग करें जिसमें केवल डॉकरफाइल ज्ञान शामिल है। बहुत बढ़िया जवाब।
Akito

"एआरजी ईएनवी" क्या करता है? क्या आप इस पर कुछ प्रकाश डाल सकते हैं? धन्यवाद।
मैक्स

@Max कि बाहर इशारा करने के लिए धन्यवाद। यह आवश्यक नहीं है
User12547645

12

बस ऐसा करने के लिए सीधे "परीक्षण" बाइनरी का उपयोग करें। आपको नोप कमांड का भी उपयोग करना चाहिए ":" यदि आप "और" स्थिति निर्दिष्ट नहीं करना चाहते हैं, तो डॉक नॉन जीरो रिटर्न मान त्रुटि के साथ बंद नहीं होता है।

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" && :

2
उसी के रूप में RUN [ -z "$YOURVAR" ] && ... || :, मेरा मानना ​​है
OneCricketeer

4
निम्न कथन के लिए, यदि var सेट है तो दोनों इको निष्पादित होते हैं। RUN test -z "$YOURVAR" || echo "var is set" && echo "var is not set"
हर्षद व्याहारे

वास्तव में। याद रखें कि वे सशर्त ब्लॉक नहीं हैं, वे क्रमिक रूप से निष्पादित करते हैं, &&सामने रखते हैं ||:test ! -z "$YOURVAR" && echo "var is set" || echo "var is not set"
ब्रांट

5

बिल्कुल जैसा कि अन्य लोगों ने बताया, शेल स्क्रिप्ट से मदद मिलेगी।

सिर्फ एक अतिरिक्त मामला, IMHO यह ध्यान देने योग्य है (किसी और के लिए जो यहां ठोकर खाता है, एक आसान मामला खोज रहा है), जो कि पर्यावरण प्रतिस्थापन है

पर्यावरण चर ( ENVकथन के साथ घोषित ) का उपयोग कुछ निर्देशों में भी किया जा सकता है, जिसकी व्याख्या चर द्वारा की जा सकती है Dockerfile

${variable_name}वाक्य रचना भी मानक बैश संशोधक के कुछ ही समर्थन करता है, नीचे निर्दिष्ट है:

  • ${variable:-word}इंगित करता है कि यदि variableसेट किया गया है तो परिणाम उस मूल्य का होगा। यदि variableसेट नहीं किया गया तो wordपरिणाम होगा।

  • ${variable:+word}इंगित करता है कि यदि variableसेट किया गया है तो wordपरिणाम होगा, अन्यथा परिणाम खाली स्ट्रिंग है।


5

स्वीकार किए जाते हैं जवाब सवाल का समाधान हो सकता है, लेकिन अगर आप बहु चाहते ifdockerfile में स्थिति, आपको लगता है कि रखने कर सकते हैं \प्रत्येक पंक्ति के अंत (कैसे आप एक खोल स्क्रिप्ट में क्या करना होगा के समान) और के साथ प्रत्येक आदेश समाप्त होने पर ;। तुम भी set -eux1 कमान के रूप में कुछ परिभाषित कर सकते हैं ।

उदाहरण:

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

4

बैश स्क्रिप्ट और अल्पाइन / सेंटोस का उपयोग करना

Dockerfile

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
....
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.