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

समस्या की शिकायत करें सोर्स देखें

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

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

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

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

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

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

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

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

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

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

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

  • Docker इंस्टॉल करें और इसे चलाने के लिए ज़रूरी अनुमतियां कॉन्फ़िगर करें.
  • Basel 0.14.1 या बाद का वर्शन इंस्टॉल करें. पिछले वर्शन में Docker सैंडबॉक्स की सुविधा काम नहीं करती.
  • अपने बिल्ड की WORKSPACE फ़ाइल में, रिलीज़ के नए वर्शन में पिन किए गए bazz-toolchains रेपो को यहां बताए गए तरीके से जोड़ें.
  • इस सुविधा को चालू करने के लिए, अपनी .bazelrc फ़ाइल में फ़्लैग जोड़ें. अगर फ़ाइल मौजूद नहीं है, तो अपने Basel प्रोजेक्ट की रूट डायरेक्ट्री में फ़ाइल बनाएं. नीचे दिए गए फ़्लैग, रेफ़रंस के तौर पर दिए गए हैं. कृपया baaz-toolchains रेपो में, .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 और इसके सभी बिल्ड ऐक्शन को सीधे तौर पर लोकल मशीन पर एक्ज़ीक्यूट करता है. यह इस बात की पुष्टि करने का भरोसेमंद तरीका है कि रिमोट तरीके से लागू करने पर, आपका बिल्ड कामयाब हो पाएगा या नहीं.

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

चरण 1: बिल्ड चलाएं

  1. Basel कमांड में --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 कंटेनर में समस्या का हल पर जाएं.

दूसरा चरण: पहचानी गई समस्याओं को ठीक करना

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

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

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

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

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

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

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

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

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

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

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

    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

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

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

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

पांचवां चरण: पहचानी गई समस्याओं को ठीक करना

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

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

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

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