सीआई के साथ डॉकटर-कंपोज़ का उपयोग करना - एक्ज़िट कोड और डीमॉनेटाइज़्ड लिंक कंटेनर से कैसे निपटें?


88

अभी हमारे जेनकिंस एजेंट हमारे प्रत्येक रेल प्रोजेक्ट के लिए एक docker-compose.yml उत्पन्न करते हैं और फिर docker-comp अप चलाते हैं। Docker-compose.yml में एक मुख्य "वेब" कंटेनर है जिसमें रेनेव और हमारे सभी अन्य रेल निर्भरताएं हैं। यह एक DB कंटेनर से जुड़ा होता है जिसमें परीक्षण Postgres DB होता है।

समस्या तब आती है जब हमें वास्तव में परीक्षणों को चलाने और निकास कोड उत्पन्न करने की आवश्यकता होती है। हमारे सीआई सर्वर केवल तभी तैनात होंगे जब परीक्षण स्क्रिप्ट 0 से बाहर निकलती है, लेकिन डॉकटर-कंपोज़ हमेशा 0 रिटर्न देता है, भले ही कंटेनर कमांड में से एक विफल हो।

दूसरा मुद्दा यह है कि DB कंटेनर अनिश्चित काल तक चलता है, इसके बाद भी जब वेब कंटेनर परीक्षण चला रहा होता है, तो docker-compose upकभी नहीं लौटता है।

क्या कोई तरीका है जिससे हम इस प्रक्रिया के लिए docker-compose का उपयोग कर सकते हैं? हमें कंटेनरों को चलाने में सक्षम होना चाहिए, लेकिन वेब कंटेनर के पूरा होने के बाद बाहर निकलें और इसे बाहर निकलें कोड वापस कर दें। अभी हम डीबी कंटेनर को स्पिन करने के लिए डॉकटर का उपयोग करके मैन्युअल रूप से अटके हुए हैं और वेब कंटेनर को --link विकल्प के साथ चलाते हैं।

जवाबों:


76

संस्करण के बाद से 1.12.0, आप --exit-code-fromविकल्प का उपयोग कर सकते हैं ।

से प्रलेखन :

- सेवा-कोड-सेवा से

चयनित सेवा कंटेनर का निकास कोड लौटाएं। इंप्लाइज - एबोर्ट-ऑन-कंटेनर-एग्जिट।


1
यदि आप docker-compose1.12.0 और इसके बाद के संस्करण का उपयोग कर रहे हैं, तो इसे करने का सही तरीका होना चाहिए । शायद यह आपका मामला भी है। एक उदाहरण हो सकता है docker-compose up --exit-code-from test-unit:। ध्यान दें कि यह मेरे लिए तब तक काम नहीं आया जब तक मैंने set -eअपनी स्क्रिप्ट की शुरुआत में इसे नहीं जोड़ा ।
एड्रियन एंटुनेज़

--exit-code-from-dहालांकि काम नहीं करता है । यह इन त्रुटियों को फेंक देगा: using --exit-code-from implies --abort-on-container-exitऔर --abort-on-container-exit and -d cannot be combined.
ericat

3
मैं ट्रैविस CI पर इस काम को प्राप्त करने में सक्षम था: travis-ci.org/coyote-team/coyote/builds/274582053 यहां ट्रैविस.आईएमएल: github.com/coyote-team-coyote/blob/master/.travis.yml # L12
सबलेस्की

2
प्रलेखन अत्याचारी है। यह किस झंडे के साथ संगत है? क्या यह केवल एक सेवा है या आप इसे कई बार पास कर सकते हैं?
worc

42

docker-compose runअपनी इच्छा से बाहर निकलने की स्थिति प्राप्त करने का सरल तरीका है। उदाहरण के लिए:

$ cat docker-compose.yml 
roit:
    image: busybox
    command: 'true'
naw:
    image: busybox
    command: 'false'
$ docker-compose run --rm roit; echo $?
Removing test_roit_run_1...
0
$ docker-compose run --rm naw; echo $?
Removing test_naw_run_1...
1

वैकल्पिक रूप से, आपके पास मृत कंटेनरों का निरीक्षण करने का विकल्प है । आप -fध्वज का उपयोग सिर्फ बाहर निकलने की स्थिति प्राप्त करने के लिए कर सकते हैं ।

$ docker-compose up
Creating test_naw_1...
Creating test_roit_1...
Attaching to test_roit_1
test_roit_1 exited with code 0
Gracefully stopping... (press Ctrl+C again to force)
$ docker-compose ps -q | xargs docker inspect -f '{{ .Name }} exited with status {{ .State.ExitCode }}'
/test_naw_1 exited with status 1
/test_roit_1 exited with status 0

Db कंटेनर के लिए जो कभी नहीं लौटता है, यदि आप उपयोग करते हैं docker-compose upतो आपको उस कंटेनर को सिगिल करने की आवश्यकता होगी; शायद वही नहीं जो आप चाहते हैं। इसके बजाय, आप docker-compose up -dअपने कंटेनरों को डीमॉनेटाइज़्ड चलाने के लिए उपयोग कर सकते हैं , और मैन्युअल रूप से कंटेनरों को मार सकते हैं जब आपका परीक्षण पूरा हो जाता है। आपके लिए लिंक किए गए कंटेनरों docker-compose run को चलाना चाहिए , लेकिन मैंने एसओ पर एक बग के बारे में बकबक सुना है जो कि अभी के अनुसार काम करने से रोक रहा है।


Docker run के साथ समस्या यह है कि यह -T के साथ चलने पर कोई आउटपुट नहीं देती है, और हम आउटपुट चाहते हैं, ताकि हम नए आउटपुट का निरीक्षण कर सकें।
लोगन सरमन

1
आप के साथ उत्पादन का निरीक्षण कर सकते @LoganSermandocker-compose logs
Kojiro

क्या रन के दौरान STDOUT में उन लॉग को लगातार पाइप करने का एक तरीका है ताकि हम इसे देख सकें जबकि सीआई बिल्ड प्रगति पर है?
लोगन सरमन

मुझे लगता है मुझे समझ नहीं आ रहा है कि आप क्यों चल रहे हैं-T
kojiro

परीक्षण चलाने के लिए हम कंटेनर के अंदर चलने वाले कुछ आदेशों में इनपुट के लिए पूछने की क्षमता रखते हैं, हम इससे बचने के लिए -T के साथ चलना चाहते हैं। उदाहरण के लिए रेंबव पूछता है कि क्या आप रूबी संस्करण को फिर से स्थापित करना चाहते हैं यदि यह पहले से मौजूद है।
लोगन सरमन

23

कोजीरो के उत्तर पर निर्माण:

docker-compose ps -q | xargs docker inspect -f '{{ .State.ExitCode }}' | grep -v '^0' | wc -l | tr -d ' '

  1. कंटेनर आईडी प्राप्त करें
  2. प्रत्येक कंटेनर आईडी के लिए अंतिम रन निकास कोड प्राप्त करें
  3. केवल स्थिति कोड जो '0' से शुरू नहीं होता है
  4. गैर-0 स्थिति कोड की संख्या की गणना करें
  5. सफेद जगह बाहर ट्रिम

कितने गैर-0 निकास कोड लौटाए गए। 0 होगा यदि सब कुछ कोड 0 के साथ बाहर निकलता है।


आप गैर-शांत आउटपुट का उपयोग भी कर सकते हैं docker-compose ps, उदाहरण के लिए: docker-compose ps | grep -c "Exit 1"आपको वह गणना देगा जहां "बाहर निकलें 1" को प्रदर्शन से मिलान किया जाता है docker-compose ps(जो परिणामों के एक सुंदर-मुद्रित सारांश तालिका प्रदान करता है)। निकास कोड "राज्य" कॉलम में सूचीबद्ध हैं।
एरिक

यह वाकई कमाल है। मेरे मामले में कंटेनरों में चल रहे टेस्ट सूट फेल होने से कंटेनर 1. के कोड से बाहर नहीं निकलते हैं। अगर कोई उनमें से कोई नहीं करता है तो मैं 1 के कोड के साथ बाहर निकल सकता हूं। कोई भी विचार नहीं। मामला?
वॉकएरैंडोफिमिथ

9

यदि आप docker-compose runअपने परीक्षणों को मैन्युअल रूप से --rmध्वज को जोड़ने के लिए उपयोग करने के लिए तैयार हैं , तो ध्वज को जोड़ना , अजीब तरह से पर्याप्त है, जो आपके कमांड की निकास स्थिति को सटीक रूप से प्रतिबिंबित करने का कारण बनता है।

यहाँ मेरा उदाहरण है:

$ docker-compose -v
docker-compose version 1.7.0, build 0d7bf73

$ (docker-compose run bash false) || echo 'Test failed!'  # False negative.

$ (docker-compose run --rm bash false) || echo 'Test failed!'  # True positive.
Test failed!

$ (docker-compose run --rm bash true) || echo 'Test failed!'  # True negative.

1
या (docker-compose run --rm ...) || exit $?त्रुटि के मामले में समाप्ति के लिए। बैश स्क्रिप्ट में उपयोगी।
अमीरेज़ा नसीरी

8

docker waitनिकास कोड प्राप्त करने के लिए उपयोग करें :

$ docker-compose -p foo up -d
$ ret=$(docker wait foo_bar_1)

foo"प्रोजेक्ट नाम" है। ऊपर दिए गए उदाहरण में, मैंने इसे स्पष्ट रूप से निर्दिष्ट किया है, लेकिन यदि आप इसकी आपूर्ति नहीं करते हैं, तो यह निर्देशिका का नाम है। barवह नाम है जिसे आप अपने docker-compose.yml में परीक्षण के तहत सिस्टम को देते हैं।

ध्यान दें कि docker logs -fसही काम करता है, भी, जब कंटेनर बंद हो जाता है तब बाहर निकलता है। तो आप डाल सकते हैं

$ docker logs -f foo_bar_1

docker-compose upऔर इसके बीच में docker waitआप अपने परीक्षणों को चला सकते हैं।


8

--exit-code-from SERVICEऔर --abort-on-container-exitउन परिदृश्यों में काम न करें जहां आपको सभी कंटेनरों को पूरा करने के लिए चलाने की आवश्यकता है, लेकिन यदि उनमें से एक जल्दी बाहर निकलता है तो असफल हो जाता है। एक उदाहरण हो सकता है कि विभिन्न कंटेनरों में 2 टेस्ट सूट चल रहे हों।

@ बिचिल के सुझाव के साथ, आप docker-composeएक स्क्रिप्ट में लपेट सकते हैं जो किसी भी कंटेनर में विफल हो जाएगी।

#!/bin/bash
set -e

# Wrap docker-compose and return a non-zero exit code if any containers failed.

docker-compose "$@"

exit $(docker-compose -f docker-compose.ci.build.yml ps -q | tr -d '[:space:]' |
  xargs docker inspect -f '{{ .State.ExitCode }}' | grep -v 0 | wc -l | tr -d '[:space:]')

फिर अपने CI सर्वर पर बस docker-compose upकरने के लिए बदल जाते हैं ./docker-compose.sh up


1
यह स्क्रिप्ट कभी भी अन्य कंटेनर (जैसे डेटाबेस, वेब ऐप) के रूप में निकास अनुभाग तक नहीं पहुंचती है। डिटैक्ड मोड में चल रहा है जैसे ही कंटेनर ऊपर आता है
बाल्दी

यह सही है, यह केवल तभी काम करता है जब आप सभी कंटेनरों को पूरा करने के लिए चलाना चाहते हैं । शायद विशेष रूप से आम नहीं, लेकिन लेखन के समय यह मेरे लिए उपयोगी था और मुझे लगा कि मैं इसे साझा करूंगा।
मैट कोल

वैसे भी अपने जवाब को उकेर दिया क्योंकि यह मुझे वहाँ से ज्यादातर मिल गया! डॉकटर प्रतीक्षा को अलग किए गए मोड में प्रत्येक परीक्षण कंटेनर पर जोड़ने से यह काम कर गया। साझा करने के लिए धन्यवाद :)
बाल्दी

2

docker-rails आपको यह बताने की अनुमति देता है कि मुख्य प्रक्रिया में किस कंटेनर का त्रुटि कोड वापस आ गया है, इसलिए आप CI सर्वर परिणाम को निर्धारित कर सकते हैं। यह सीआई के लिए एक महान समाधान है और डॉक के साथ रेल के लिए विकास है।

उदाहरण के लिए

exit_code: web

आपके आदेश के परिणामस्वरूप कंटेनरों से बाहर निकलने का कोड docker-rails.ymlनिकलेगा । मानक के चारों ओर बस एक मेटा रैपर है जो आपको विभिन्न वातावरणों के लिए एक ही आधार विन्यास को पुन: उपयोग / पुन: उपयोग करने की क्षमता देता है अर्थात विकास बनाम परीक्षण बनाम समानांतर_टेस्ट।webdocker-rails ci testdocker-rails.ymldocker-compose.yml


2

यदि आप एक docker इंजन पर एक ही नाम के साथ और अधिक docker- कम्पोज़ सेवा चला सकते हैं, और आपको सटीक नाम नहीं पता है:

docker-compose up -d
(exit "${$(docker-compose logs -f test-chrome)##* }")

echo %? - टेस्ट-क्रोम सेवा से बाहर निकलने का कोड

लाभ:

  • बाहर निकलने के लिए सटीक सेवा की प्रतीक्षा करें
  • कंटेनर नाम नहीं, सेवा नाम का उपयोग करता है

2

आप इसके साथ निकास स्थिति देख सकते हैं:

echo $(docker-compose ps | grep "servicename" | awk '{print $4}')

इसे शुरू करने के लिए धन्यवाद। यहाँ इस एक का मेरा संस्करण है (जो मेरे लिए बेहतर काम करता है b / c मुझे लगता है कि कमांड आउटपुट प्रारूप बदल गया है क्योंकि यह उत्तर लिखा गया था) -docker-compose ps | grep servicename | grep -v 'Exit 0' && echo "Automation or integration tests failed." && exit 1
DTrejo
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.