डॉक रन के माध्यम से शेल स्क्रिप्ट में तर्क कैसे पारित करें


131

मैं डॉकटर जगत के लिए नया हूं। मुझे एक शेल स्क्रिप्ट का आह्वान करना है जो एक डॉकटर कंटेनर के माध्यम से कमांड लाइन तर्क लेता है। Ex: मेरी शेल स्क्रिप्ट इस प्रकार है:

#!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
मुझे लगता है कि ENTRYPOINT जाने का रास्ता है अगर आप नहीं चाहते कि एंड-यूज़र सीधे file.sh के बारे में जाने।
greg.kindel

आप इस तरह से एक स्क्रिप्ट कैसे शुरू कर सकते हैं docker run -ti test /file.sh abc। मुझे लगता है कि स्क्रिप्ट नहीं चलेगी क्योंकि यह होना चाहिए docker run -ti test sh /file.sh abc। श या / बिन / श इसे सही चलाएगा।
वामसीधर मुग्गुल्ला

1
यहां आने वाले किसी और के लिए। / Usr / bin / env ट्रिक वैकल्पिक शैली की प्राथमिकता है, इसे काम करने की आवश्यकता नहीं है। यह भी #! लाइन इंगित करती है कि कौन से दुभाषिए को डिफ़ॉल्ट का उपयोग करना है। तो यह सिर्फ स्क्रिप्ट को कॉल करके चल सकता है।
wheredidthatnamecomefrom

163

इस स्क्रिप्ट में 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" भूल जाते हैं जैसा कि मैंने किया, तो यह काम नहीं करेगा।
केव

6
किसी कारण के लिए, इस के साथ काम नहीं करता हैENTRYPOINT ./file.sh
phil294

6
chmod +x file.shनिष्पादन योग्य ध्वज सेट करना न भूलें ।
टॉपसिप

1
@kev, क्या आप जानते हैं कि ऐसा क्यों है? क्या बीच का अंतर है ["/file.sh"]और /file.shया यहाँ तक कि[/file.sh]
Nitzankin

1
@Nitzankin के लिए मेरा जवाब देखें कि क्यों उचित जॅन्सन फॉर्मेटिंग की आवश्यकता है।
BMitch

60

डॉकर के साथ, इस प्रकार की जानकारी को पारित करने का उचित तरीका पर्यावरण चर है।

तो उसी डॉकरफाइल के साथ, स्क्रिप्ट को बदल दें

#!/bin/bash
echo $FOO

निर्माण के बाद, निम्नलिखित डॉक कमांड का उपयोग करें:

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

20
यह सबसे ज्यादा मतदान का जवाब क्यों है? Env vars जानकारी पास करने का एक और तरीका है, लेकिन वह नहीं है जो ओपी पूछ रहा है। और निश्चित रूप से कंटेनर के पास आर्ग करने के लिए ओपी की इच्छा के बारे में बिल्कुल अनुचित कुछ भी नहीं है।
आंशिक रूप से बादल छाए रहेंगे

8
@PartlyCloudy मुझे लगता है कि लोग इसे पसंद करते हैं क्योंकि यह स्पष्ट रूप से गलत होने के बावजूद "उचित" उत्तर देने के लिए उद्देश्य रखता है। डॉकर का एक प्रमुख डिजाइन सिद्धांत सामान्य ज्ञान पर हठधर्मिता को प्राथमिकता देना है।
अगस्त

1
@ उद्घोषक: इस उत्तर को बेहतर बनाने के लिए, शायद आप समझाएं कि आपको क्यों लगता है कि यह उत्तर "स्पष्ट रूप से गलत है"?
एमिल स्टेनस्ट्रॉम

2
XY समस्याओं का एक टन SO पर है। चूंकि ओपी ने कहा कि वे डॉकटर के लिए नए थे, इसलिए यह पूरी तरह से उचित है कि एक लक्ष्य प्राप्त करने के लिए अनुशंसित तरीका दिखाया जाए। इस प्रकार यह एक महान जवाब है।
colm.anseo

1
वेरिएबल्स को बनाने के बजाय काम करने का सबसे आसान तरीका है कि बिल्ड ऑर्गन्स और वह सब गड़बड़ हो जाए। पर्यावरण चर के रूप में रहस्यों को पारित करने के लिए बहुत उपयोगी है।
अरविंद श्रीधरन

32

यहां बातचीत करने वाली कुछ चीजें हैं:

  1. docker run your_image arg1 arg2का मान बदल देगा CMDके साथ arg1 arg2। यह CMD का पूर्ण प्रतिस्थापन है, इसमें अधिक मूल्यों को शामिल नहीं किया गया है। यही कारण है कि आप अक्सर docker run some_image /bin/bashकंटेनर में बैश शेल को चलाते हैं।

  2. जब आपके पास एक ENTRYPOINT और एक CMD मूल्य दोनों परिभाषित होता है, तो डॉकटर कंटेनर को दोनों को समेट कर और उस समाप्‍त कमांड को चलाकर शुरू करता है। इसलिए यदि आप अपने प्रवेश बिंदु को परिभाषित करते हैं file.sh, तो आप अब कंटेनर को अतिरिक्त आर्गन्स के साथ चला सकते हैं जो कि आर्ग्स के रूप में पारित हो जाएगा file.sh

  3. डॉक में एंट्रीपॉइंट और कमांड में दो सिंटैक्स होते हैं, एक स्ट्रिंग सिंटैक्स जो एक शेल लॉन्च करेगा, और एक जसन सिंटैक्स जो एक निष्पादन करेगा। शेल, IO पुनर्निर्देशन जैसी चीजों को संभालने के लिए उपयोगी है, एक साथ कई आदेशों का पीछा करते हुए (जैसे चीजें &&), चर प्रतिस्थापन, आदि। हालांकि, यह शेल सिग्नल से निपटने के रास्ते में मिलता है (यदि आपने कभी 10 सेकंड रुकने की देरी देखी है। एक कंटेनर, यह अक्सर कारण होता है) और एक प्रविष्टि और आदेश को एक साथ समेटने के साथ। यदि आप अपने एंट्रीपॉइंट को एक स्ट्रिंग के रूप में परिभाषित करते हैं, तो यह चलेगा /bin/sh -c "file.sh", जो अकेले ठीक है। लेकिन अगर आपके पास एक कमांड भी एक स्ट्रिंग के रूप में परिभाषित है, तो आप कुछ ऐसा देखेंगे जैसे /bin/sh -c "file.sh" /bin/sh -c "arg1 arg2"कि कमांड आपके कंटेनर के अंदर लॉन्च किया जा रहा है, इतना अच्छा नहीं है। इन दो विकल्पों के परस्पर क्रिया के बारे में अधिक जानकारी के लिए यहाँ तालिका देखें

  4. शेल -cविकल्प केवल एक तर्क लेता है। उसके बाद सब कुछ उस एकल तर्क के रूप $1में $2, इत्यादि के रूप में पारित हो जाएगा , लेकिन एक एम्बेडेड शेल स्क्रिप्ट में नहीं जब तक कि आप स्पष्ट रूप से आर्ग्स पारित नहीं करते। Ie /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 / प्रोफाइल स्रोत प्राप्त करने के लिए अपना प्रवेश बिंदु सेट करने के लिए प्रयोग किया था, लेकिन बाद में सोच रहा था कि कोई भी आर्गन नहीं किया जाएगा जो शेल रन करने के लिए पास किए गए शेल स्क्रिप्ट में जाएगा ... आपका उत्तर साफ़ हो गया है कि, धन्यवाद !
एपर्टेक्स

23

मेरे पास एक स्क्रिप्ट फ़ाइल है जो वास्तव में चीजों को चलाती है। यह भिन्न फ़ाइल अपेक्षाकृत जटिल हो सकती है। चलो इसे "run_container" कहते हैं। यह स्क्रिप्ट कमांड लाइन से तर्क लेती है:

run_container p1 p2 p3

एक साधारण run_container हो सकता है:

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

मैं क्या करना चाहता हूं, "डॉकिंग" के बाद मैं इस कंटेनर को इस तरह से डॉक कमांड लाइन पर मापदंडों के साथ स्टार्टअप करने में सक्षम होना चाहूंगा:

docker run image_name p1 p2 p3

और run_container स्क्रिप्ट को पैरामीटर के रूप में p1 P2 p3 के साथ चलाया जाए।

यह मेरा समाधान है:

Dockerfile:

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

मेरी बैश फ़ाइल में स्विच / केस स्टेटमेंट जोड़ने के बाद, ENTRYPOINT ["run_container.sh"] अब मेरे लिए काम नहीं करता, लेकिन ENTRYPOINT ["sh", "-c", "run_container.sh"] अब मेरे मापदंडों को स्वीकार नहीं करेगा। इस समाधान (@davidchambers सुझाव के साथ) ने मेरे लिए काम किया।
रहमिल्टन

10

यदि आप इसे @ टाइम चलाना चाहते हैं:

CMD /bin/bash /file.sh arg1

अगर आप इसे चलाना चाहते हैं तो @run समय:

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

फिर मेजबान शेल में

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

2
ENTRYPOINTओपी के लिए एक अच्छा जवाब है जो मुझे लगता है कि रनटाइम चाहता था, लेकिन अगर आप वास्तव में समय चर का निर्माण करना चाहते हैं तो यह जवाब अभी टूट गया है। का प्रयोग करें ARGऔर docker 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"]

प्रविष्टि में

#!/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

कुछ टिप्पणी और सीमाएं .... "के साथ कमांड:" कट-डी में बदलाव की जरूरत है ':' और docker run -d --rm $ IMG_NAME "bash: echo $ PATH" जैसे कमांड होस्ट के बजाय मेजबान पथ मान दिखाएंगे एक
wagnermarques
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.