शेल स्क्रिप्ट का उपयोग कर एक डॉक कंटेनर के अंदर एक स्क्रिप्ट चलाना


85

मैं एक डॉक कंटेनर स्थापित करने के लिए एक शेल स्क्रिप्ट बनाने की कोशिश कर रहा हूं। मेरी स्क्रिप्ट फ़ाइल इस प्रकार है:

#!bin/bash

docker run -t -i -p 5902:5902 --name "mycontainer" --privileged myImage:new /bin/bash

इस स्क्रिप्ट फ़ाइल को चलाने से कंटेनर एक नए इनवॉइस बैश में चलेगा।

अब मुझे एक स्क्रिप्ट फ़ाइल (test.sh) चलाने की आवश्यकता है जो पहले से ही दी गई शेल स्क्रिप्ट से कंटेनर के अंदर है। (जैसे: cd /path/to/test.sh &&/test.sh) वह कैसे करें?


1
क्यों नहीं उपयोग WORKDIRऔर CMD?
धर्मिट

1
आप शायद यहाँ --privileged का उपयोग नहीं करना चाहते हैं। देखें: stackoverflow.com/questions/36425230/…
सीएमपी

जवाबों:


121

आप एक चल रहे कंटेनर में एक कमांड चला सकते हैं docker exec [OPTIONS] CONTAINER COMMAND [ARG...]:

docker exec mycontainer /path/to/test.sh

और बैश सत्र से चलने के लिए:

docker exec -it mycontainer /bin/bash

वहां से आप अपनी स्क्रिप्ट चला सकते हैं।


6
क्या होगा अगर मुझे पहले / बिन / बैश में प्रवेश करना है और फिर उस बैश के अंदर कमांड चलाना है?
zappy

44
आप सीधे होस्ट से स्थानीय स्क्रिप्ट भी चला सकते हैं। docker exec -i mycontainer bash < mylocal.sh यह स्थानीय होस्ट स्क्रिप्ट को पढ़ता है और इसे कंटेनर के अंदर चलाता है। आप इसे अन्य चीजों के साथ भी कर सकते हैं (जैसे .tgz फाइलें टार में पाइप की गई) - इसके सिर्फ '-i' का उपयोग करके कंटेनर प्रोसेस स्टैड इनपुट में डाल सकते हैं।
मार्विन

@ मारविन पॉवरशेल में बराबर क्या है? "<" वर्ण पहचाना नहीं गया है।
निकीवकी

1
मैं एक powershell गुरु (शुक्र) नहीं कर रहा हूँ, लेकिन मैं इतना चारों ओर फिरते और पाया stackoverflow.com/a/11788475/500902 । तो, शायद Get-Content mylocal.sh | docker exec -i mycontainer bash। मुझे नहीं पता कि क्या यह काम करता है।
मार्विन

97

यह मानते हुए कि आपका डॉकटर कंटेनर ऊपर है और चल रहा है, आप निम्नानुसार कमांड चला सकते हैं:

docker exec mycontainer /bin/sh -c "cmd1;cmd2;...;cmdn"

2
मुझे यह उत्तर पसंद है; आपको कमांड या कमांड सेट करने के लिए डॉकटर कंटेनर में लॉग इन नहीं करना है। धन्यवाद!
हेटम जबर

क्या आप जानते हैं कि इसे कैसे आगे बढ़ाया जाए और /bin/sh -c "cmd1; cmd2; ...; cmdn"शेल कमांड के मान के रूप में संपूर्ण कमांड ( ) पास की जाए ? मैं पूछता हूं क्योंकि 'docker run' एक उद्धृत कमांड के बजाय एक एकल कमांड और व्यक्तिगत अयोग्य तर्क की अपेक्षा करता है।
davidA

@meowsqueak: यह उत्तर बताता है कि उस कंटेनर में लॉग किए बिना पहले से ही बनाए गए और चल रहे कंटेनर के अंदर कई कमांड कैसे चलाएं, जो स्वचालन में सहायक है। लेकिन यदि आप कंटेनर निर्माण के समय (पुनश्च: डोकर रन कमांड बनाता है और कंटेनर शुरू होता है) में कई आदेशों को चलाने के लिए चाहते हैं, तो आप इस एक ही धागे में जवाब का पालन करते हुए कि प्राप्त कर सकते हैं stackoverflow.com/a/41363989/777617
साइक्लोप्स

इसके स्थान पर cmd1, मुझे पूरे लूप में पास होने की आवश्यकता है - लेकिन यह लूप स्टेटमेंट और स्टेटमेंट के ;बाद उम्मीद करता है। मैं एकल कमांड के रूप में पूरे लूप को कैसे चला सकता हूं ? क्या यह संभव है? cmd1
निकोलस के

18

मैं इसी प्रश्न के लिए एक उत्तर खोज रहा था और मेरे लिए Dockerfile समाधान में ENTRYPOINT मिला ।

Dockerfile

...
ENTRYPOINT /my-script.sh ; /my-script2.sh ; /bin/bash

अब लिपियों को निष्पादित किया जाता है जब मैं कंटेनर शुरू करता हूं और स्क्रिप्ट निष्पादित होने के बाद मुझे बैश प्रॉम्प्ट मिलता है।


6

आप अपनी डॉक छवि में एक स्थानीय निर्देशिका को भी माउंट कर सकते हैं और अपने में स्क्रिप्ट का स्रोत बना सकते हैं .bashrc। जब तक आप इसे हर नए शेल पर निष्पादित नहीं करना चाहते, तब तक स्क्रिप्ट को फ़ंक्शंस से युक्त करना न भूलें। (यह अद्यतन सूचना देखने के लिए पुराना है।)

मैं इस समाधान का उपयोग कर रहा हूँ कि docker उदाहरण के बाहर स्क्रिप्ट को अपडेट करने में सक्षम हो। इस तरह मुझे छवि को फिर से चलाने की ज़रूरत नहीं है यदि परिवर्तन होते हैं, तो मैं बस एक नया खोल खोलता हूं। (एक खोल को फिर से खोलने से छुटकारा मिला - अपडेट नोटिस देखें)

यहां बताया गया है कि आप अपनी वर्तमान निर्देशिका को कैसे बांधते हैं:

docker run -it -v $PWD:/scripts $my_docker_build /bin/bash

अब आपकी वर्तमान निर्देशिका /scriptsआपके docker उदाहरण के लिए बाध्य है ।

(आउटडेटेड) अपने .bashrcपरिवर्तनों को सहेजने के लिए इस आदेश के साथ अपनी कार्य छवि बनाएं:

docker commit $container_id $my_docker_build

अपडेट करें

इस समस्या को हल करने के लिए मैं अब हर परिवर्तन के लिए एक नया खोल खोल सकता हूं:

डॉकटरफाइल में मैं खुद को जोड़ता हूं RUN echo "/scripts/bashrc" > /root/.bashrc"। अंदर zshrcमैं स्क्रिप्ट निर्देशिका को पथ में निर्यात करता हूं। स्क्रिप्ट निर्देशिका में अब एक के बजाय कई फाइलें हैं। अब मैं सीधे सभी लिपियों को कॉल कर सकता हूं बिना हर बदलाव के एक उप खोल खोल सकता हूं।

BTW आप अपने कंटेनर के बाहर इतिहास फ़ाइल को परिभाषित कर सकते हैं। इस तरह से यह आवश्यक नहीं है कि अब कोई बैश परिवर्तन किया जाए।


बहुत देर..! @ जेवियर पहले से ही एक सीधे आगे समाधान दिखाता है !! मुझे लगता है कि एक अभी भी बेहतर है।
झप्पी

2
@ जेवियर से समाधान ने मेरे लिए इस समस्या को आसानी से हल नहीं किया - लेकिन मेरा समाधान किया, मैंने सोचा कि यह उन लोगों के लिए दिलचस्प होगा जिनके पास एक समान समस्या थी जहां वे अपडेट करने के लिए docker की छवि को पुनः आरंभ नहीं करना चाहते हैं उन कार्यों को देखें जिनकी उन्हें आवश्यकता है। उदाहरण के लिए यदि आप एक ही समय में एक बार फिर से शुरू नहीं करना चाहते हैं तो एक देव क्लस्टर को स्पिन करने के लिए कई डॉकटर छवियों का उपयोग करें।
देवलोक

3

यदि आप एक चालू कंटेनर नहीं चाहते (या हैं), तो आप अपनी स्क्रिप्ट को सीधे runकमांड से कॉल कर सकते हैं ।

पुनरावृति के छोटे -i -tतर्कों को हटा दें और इसका उपयोग करें:

    $ docker run ubuntu:bionic /bin/bash /path/to/script.sh

यह अन्य लिपियों के लिए भी काम नहीं करेगा (परीक्षण नहीं):

    $ docker run ubuntu:bionic /usr/bin/python /path/to/script.py


0

यदि आप एक ही कमांड को कई उदाहरणों पर चलाना चाहते हैं, तो आप ऐसा कर सकते हैं:

for i in c1 dm1 dm2 ds1 ds2 gtm_m gtm_sl; do docker exec -it $i /bin/bash -c "service sshd start"; done
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.