Docker सैंडबॉक्स की मदद से, Bazel रिमोट एक्ज़ीक्यूशन की समस्या हल करना

7.3 · 7.2 · 7.1 · 7.0 · 6.5

हो सकता है कि स्थानीय तौर पर काम करने वाले Bazel बिल्ड, रिमोट तौर पर चलाए जाने पर काम न करें. ऐसा, उन पाबंदियों और ज़रूरी शर्तों की वजह से होता है जिनका स्थानीय बिल्ड पर कोई असर नहीं पड़ता. ऐसी असफलता की सबसे आम वजहों के बारे में, रिमोट एक्ज़िक्यूशन के लिए बेज़ल रूल को लागू करना लेख में बताया गया है.

इस पेज में Docker सैंडबॉक्स सुविधा की मदद से, रिमोट तरीके से एक्ज़ीक्यूट करने की सुविधा की मदद से आम तौर पर होने वाली समस्याओं की पहचान करने और उन्हें हल करने का तरीका बताया गया है. इसमें, रिमोट तरीके से एक्ज़ीक्यूट किए जाने वाले बिल्ड के बराबर पाबंदियां लगाई जाती हैं. इससे आपको अपने बिल्ड की समस्या को हल करने में मदद मिलती है. इसके लिए, आपको रिमोट एक्ज़ीक्यूशन सेवा की ज़रूरत नहीं होती.

Docker सैंडबॉक्स की सुविधा, रिमोट तरीके से प्रोग्राम चलाने पर लगी पाबंदियों की नकल करती है. ये पाबंदियां इस तरह से लागू होती हैं:

  • बिल्ड ऐक्शन, टूलचेन कंटेनर में लागू होते हैं. एक ही टूलचेन कंटेनर का इस्तेमाल करके, अपने बिल्ड को स्थानीय तौर पर या कहीं से भी चलाया जा सकता है. ऐसा करने के लिए, कंटेनर वाली रिमोट एक्ज़ीक्यूशन की सुविधा का इस्तेमाल किया जा सकता है.

  • कोई भी अतिरिक्त डेटा, कंटेनर की सीमा से बाहर नहीं जाता. सिर्फ़ साफ़ तौर पर बताए गए इनपुट और आउटपुट, कंटेनर में जाते हैं और उससे बाहर निकलते हैं. ऐसा, उससे जुड़ी बिल्ड ऐक्शन पूरी होने के बाद ही होता है.

  • हर ऐक्शन, नए कंटेनर में लागू होता है. स्पॉन किए गए हर बिल्ड ऐक्शन के लिए, एक नया और यूनीक कंटेनर बनाया जाता है.

इन समस्याओं को हल करने के लिए, इनमें से किसी एक तरीके का इस्तेमाल करें:

  • मूल रूप से समस्या हल करना. इस तरीके से, Bazel और उसकी बिल्ड ऐक्शन, आपकी लोकल मशीन पर नेटिव तौर पर चलते हैं. Docker सैंडबॉक्स सुविधा, रिमोट ऐक्शन के बराबर के बिल्ड पर पाबंदियां लगाती है. हालांकि, इस तरीके से आपके बिल्ड में लीक होने वाले लोकल टूल, राज्यों, और डेटा का पता नहीं चलेगा. इसकी वजह से, कहीं से भी कोड लागू करने में समस्या होगी.

  • Docker कंटेनर में समस्या हल करना. इस तरीके का इस्तेमाल करके, Bagel और इसके बिल्ड ऐक्शन Docker कंटेनर में चलते हैं. इससे आपको लोकल मशीन से बिल्ड में लीक होने वाले टूल, राज्यों, और डेटा का पता लगाने की सुविधा मिलती है. साथ ही, आपको रिमोट एक्ज़ीक्यूशन की तरह ही पाबंदियां भी लगानी पड़ती हैं. इस तरीके से, आपको अपने बिल्ड के बारे में अहम जानकारी मिलती है. भले ही, बिल्ड के कुछ हिस्से काम न कर रहे हों. यह तरीका एक्सपेरिमेंट के तौर पर उपलब्ध है और इसे आधिकारिक तौर पर इस्तेमाल नहीं किया जा सकता.

ज़रूरी शर्तें

अगर आपने अब तक ऐसा नहीं किया है, तो समस्या हल करने से पहले ये काम करें:

  • Docker इंस्टॉल करें और इसे चलाने के लिए ज़रूरी अनुमतियां कॉन्फ़िगर करें.
  • Bazel 0.14.1 या इसके बाद का वर्शन इंस्टॉल करें. Docker के पिछले वर्शन में, सैंडबॉक्स की सुविधा काम नहीं करती.
  • यहां बताए गए तरीके से, अपने बिल्ड की WORKSPACE फ़ाइल में, रिलीज़ के सबसे नए वर्शन पर पिन किए गए bazel-toolchains रेपो को जोड़ें.
  • इस सुविधा को चालू करने के लिए, अपनी .bazelrc फ़ाइल में फ़्लैग जोड़ें. अगर फ़ाइल मौजूद नहीं है, तो अपने Bazel प्रोजेक्ट की रूट डायरेक्ट्री में फ़ाइल बनाएं. नीचे दिए गए फ़्लैग, रेफ़रंस के तौर पर दिए गए हैं. कृपया bazel-toolchains repo में सबसे नई .bazelrc फ़ाइल देखें और कॉन्फ़िगरेशन docker-sandbox के लिए, वहां बताए गए फ़्लैग की वैल्यू कॉपी करें.
# Docker Sandbox Mode
build:docker-sandbox --host_javabase=<...>
build:docker-sandbox --javabase=<...>
build:docker-sandbox --crosstool_top=<...>
build:docker-sandbox --experimental_docker_image=<...>
build:docker-sandbox --spawn_strategy=docker --strategy=Javac=docker --genrule_strategy=docker
build:docker-sandbox --define=EXECUTOR=remote
build:docker-sandbox --experimental_docker_verbose
build:docker-sandbox --experimental_enable_docker_sandbox

अगर आपके नियमों को अतिरिक्त टूल की ज़रूरत है, तो ये काम करें:

  1. Dockerfile का इस्तेमाल करके टूल इंस्टॉल करके और इमेज को लोकल तौर पर बिल्ड करके, कस्टम Docker कंटेनर बनाएं.

  2. ऊपर दिए गए --experimental_docker_image फ़्लैग की वैल्यू को अपने कस्टम कंटेनर इमेज के नाम से बदलें.

मूल रूप से समस्या हल करना

यह तरीका Basel और इसके सभी बिल्ड ऐक्शन को सीधे तौर पर लोकल मशीन पर एक्ज़ीक्यूट करता है. यह इस बात की पुष्टि करने का भरोसेमंद तरीका है कि रिमोट तरीके से लागू करने पर, आपका बिल्ड कामयाब हो पाएगा या नहीं.

हालांकि, इस तरीके से, स्थानीय तौर पर इंस्टॉल किए गए टूल, बाइनरी, और डेटा आपके बिल्ड में लीक हो सकते हैं. ऐसा खास तौर पर तब होता है, जब इसमें कॉन्फ़िगर-स्टाइल WORKSPACE नियमों का इस्तेमाल किया जाता है. इस तरह की जानकारी के लीक होने की वजह से, रिमोट तरीके से एक्ज़ीक्यूट करने में समस्याएं आएंगी. उनका पता लगाने के लिए, मूल रूप से समस्या हल करने के अलावा, Docker कंटेनर में समस्या हल करें पर जाएं.

पहला चरण: बिल्ड चलाना

  1. अपने बिल्ड को लागू करने वाले Bazel कमांड में --config=docker-sandbox फ़्लैग जोड़ें. उदाहरण के लिए:

    bazel --bazelrc=.bazelrc build --config=docker-sandbox target
  2. बिल्ड चलाएं और इसके पूरा होने का इंतज़ार करें. Docker सैंडबॉक्स की सुविधा की वजह से, बिल्ड सामान्य से चार गुना धीमे चलेगा.

आपको यह गड़बड़ी दिख सकती है:

ERROR: 'docker' is an invalid value for docker spawn strategy.

अगर ऐसा किया जाता है, तो --experimental_docker_verbose फ़्लैग की मदद से बिल्ड को फिर से चलाएं. इस फ़्लैग से वर्बोस एरर मैसेज चालू होते हैं. आम तौर पर, यह गड़बड़ी Docker के गलत तरीके से इंस्टॉल होने या मौजूदा उपयोगकर्ता खाते में इसे चलाने की अनुमतियां न होने की वजह से होती है. ज़्यादा जानकारी के लिए, Docker दस्तावेज़ देखें. अगर समस्याएं बनी रहती हैं, तो Docker कंटेनर में समस्या हल करना लेख पर जाएं.

दूसरा चरण: समस्याओं को हल करना

आम तौर पर होने वाली सबसे ज़्यादा समस्याएं नीचे दी गई हैं. साथ ही, उन्हें ठीक करने के तरीके भी बताए गए हैं.

  • Bazel के रनफ़ाइल ट्री में रेफ़र की गई फ़ाइल, टूल, बाइनरी या संसाधन मौजूद नहीं है.. पुष्टि करें कि जिन टारगेट पर असर पड़ा है उनकी सभी डिपेंडेंसी के बारे में साफ़ तौर पर एलान किया गया हो. ज़्यादा जानकारी के लिए, इंप्लिसिट डिपेंडेंसी मैनेज करना देखें.

  • ऐब्सलूट पाथ या PATH वैरिएबल से जुड़ी फ़ाइल, टूल, बाइनरी या रिसॉर्स मौजूद नहीं हैं. पुष्टि करें कि टूलचेन कंटेनर में सभी ज़रूरी टूल इंस्टॉल किए गए हैं. साथ ही, टूलचेन के नियमों का इस्तेमाल करके, मौजूद न होने वाले संसाधन की जानकारी देने वाली डिपेंडेंसी का सही तरीके से एलान करें. ज़्यादा जानकारी के लिए, टूलचेन के नियमों की मदद से, बिल्ड टूल को शुरू करना देखें.

  • बाइनरी को लागू नहीं किया जा सका. बिल्ड के नियमों में से एक, एक ऐसी बाइनरी का रेफ़रंस दे रहा है जो एक्ज़ीक्यूशन एनवायरमेंट (Docker कंटेनर) के साथ काम नहीं करती. ज़्यादा जानकारी के लिए, प्लैटफ़ॉर्म पर निर्भर बाइनरी मैनेज करना देखें. अगर आपको समस्या हल करने में समस्या आ रही है, तो मदद पाने के लिए bazel-discuss@google.com पर संपर्क करें.

  • @local-jdk की एक फ़ाइल मौजूद नहीं है या उसकी वजह से गड़बड़ियां हो रही हैं. आपकी स्थानीय मशीन पर मौजूद Java बाइनरी, बिल्ड में लीक हो रही हैं. हालांकि, ये बिल्ड के साथ काम नहीं करती हैं. अपने नियमों और टारगेट में, @local_jdk के बजाय java_toolchain का इस्तेमाल करें. अगर आपको और सहायता चाहिए, तो bazel-discuss@google.com पर संपर्क करें.

  • अन्य गड़बड़ियां. मदद पाने के लिए, bazel-discuss@google.com पर संपर्क करें.

Docker कंटेनर में समस्या हल करना

इस तरीके से, Baze, होस्ट Docker कंटेनर के अंदर चलता है और Ba पैकेज की बिल्ड कार्रवाइयां, Docker सैंडबॉक्स सुविधा से पैदा होने वाले अलग-अलग टूलचेन कंटेनर के अंदर लागू होती हैं. सैंडबॉक्स, हर बिल्ड ऐक्शन के लिए एक नया टूलचेन कंटेनर बनाता है. साथ ही, हर टूलचेन कंटेनर में सिर्फ़ एक ऐक्शन लागू होता है.

इस तरीके से, होस्ट के एनवायरमेंट में इंस्टॉल किए गए टूल पर ज़्यादा बेहतर तरीके से कंट्रोल किया जा सकता है. बिल्ड को चलाने की प्रोसेस को, बिल्ड ऐक्शन को चलाने की प्रोसेस से अलग करके और इंस्टॉल किए गए टूल को कम से कम रखकर, यह पुष्टि की जा सकती है कि आपके बिल्ड में, स्थानीय रनटाइम एनवायरमेंट पर कोई डिपेंडेंसी है या नहीं.

पहला चरण: कंटेनर बनाना

  1. एक Dockerfile बनाएं जो Docker कंटेनर बनाता है और कम से कम बिल्ड टूल के सेट के साथ Bazel इंस्टॉल करता है:

    FROM debian:stretch
    
    RUN apt-get update && apt-get install -y apt-transport-https curl software-properties-common git gcc gnupg2 g++ openjdk-8-jdk-headless python-dev zip wget vim
    
    RUN curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add -
    
    RUN add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"
    
    RUN apt-get update && apt-get install -y docker-ce
    
    RUN wget https://releases.bazel.build/<latest Bazel version>/release/bazel-<latest Bazel version>-installer-linux-x86_64.sh -O ./bazel-installer.sh && chmod 755 ./bazel-installer.sh
    
    RUN ./bazel-installer.sh
    
  2. कंटेनर को bazel_container के तौर पर बनाएं:

    docker build -t bazel_container - < Dockerfile

दूसरा चरण: कंटेनर शुरू करना

नीचे दिए गए निर्देश का इस्तेमाल करके, Docker कंटेनर शुरू करें. कमांड में, अपने होस्ट पर उस सोर्स कोड का पाथ बदलें जिसे आपको बनाना है.

docker run -it \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /tmp:/tmp \
  -v your source code directory:/src \
  -w /src \
  bazel_container \
  /bin/bash

यह निर्देश, कंटेनर को रूट के तौर पर चलाता है, डॉकर सॉकेट को मैप करता है, और /tmp डायरेक्ट्री को माउंट करता है. इससे Basel को अन्य Docker कंटेनर बनाने और उन कंटेनर के साथ फ़ाइलें शेयर करने के लिए, /tmp में मौजूद डायरेक्ट्री का इस्तेमाल करने की अनुमति मिलती है. आपका सोर्स कोड, कंटेनर में /src पर उपलब्ध है.

कमांड, debian:stretch बेस कंटेनर से शुरू होती है. इसमें, टूलचेन कंटेनर के तौर पर इस्तेमाल किए गए rbe-ubuntu16-04 कंटेनर के साथ काम न करने वाली बाइनरी शामिल हैं. अगर स्थानीय एनवायरमेंट से बाइनरी, टूलचेन कंटेनर में लीक हो रही हैं, तो इससे बिल्ड में गड़बड़ियां होंगी.

तीसरा चरण: कंटेनर को टेस्ट करना

Docker कंटेनर की जांच करने के लिए, उसमें ये कमांड चलाएं:

docker ps
bazel version

चौथा चरण: बिल्ड चलाना

नीचे दिखाए गए तरीके से बिल्ड चलाएं. आउटपुट यूज़र रूट होता है, ताकि वह उस डायरेक्ट्री से मेल खाता हो जो होस्ट कंटेनर के अंदर उसी ऐब्सलूट पाथ से ऐक्सेस की जा सकती है. इसमें बेज़ल, डॉकर सैंडबॉक्स सुविधा के ज़रिए बनाए गए टूलचेन कंटेनर से चलता है. इसमें बेज़ल के बिल्ड ऐक्शन चल रहे होते हैं. साथ ही, उस लोकल मशीन से जिस पर होस्ट और ऐक्शन कंटेनर चलते हैं.

bazel --output_user_root=/tmp/bazel_docker_root --bazelrc=.bazelrc \ build --config=docker-sandbox target

पांचवां चरण: समस्याओं को हल करना

बिल्ड फ़ेल होने की समस्या को इस तरह ठीक किया जा सकता है:

  • अगर "डिस्क में स्टोरेज खत्म हो गया है" गड़बड़ी होने की वजह से बिल्ड फ़ेल हो जाता है, तो इस सीमा को बढ़ाया जा सकता है. इसके लिए, --memory=XX फ़्लैग वाले होस्ट कंटेनर को शुरू करें. इसमें, गीगाबाइट (जीबी) में, डिस्क के लिए तय की गई जगह XX है. यह सुविधा, एक्सपेरिमेंट के तौर पर उपलब्ध है. इसलिए, ऐसा हो सकता है कि यह अलग तरह का व्यवहार करे.

  • अगर विश्लेषण या लोड करने के दौरान बिल्ड पूरा नहीं होता है, तो इसका मतलब है कि WORKSPACE फ़ाइल में बताए गए आपके एक या एक से ज़्यादा बिल्ड नियम, रिमोट तौर पर लागू करने के साथ काम नहीं करते. संभावित वजहों और समाधानों के बारे में जानने के लिए, रिमोट एक्ज़ीक्यूशन के लिए बेज़ल नियमों को अपनाना देखें.

  • अगर बिल्ड किसी अन्य वजह से पूरा नहीं हो पाता है, तो दूसरा चरण: पहचानी गई समस्याओं को ठीक करना में दिए गए समस्या हल करने के तरीके देखें.