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

समस्या की शिकायत करें सोर्स देखें Nightly · 8.4 · 8.3 · 8.2 · 8.1 · 8.0 · 7.6

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

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

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

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

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

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

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

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

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

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

समस्या हल करने की प्रक्रिया शुरू करने से पहले, अगर आपने ये काम पहले से नहीं किए हैं, तो इन्हें करें:

  • Docker इंस्टॉल करें और इसे चलाने के लिए ज़रूरी अनुमतियां कॉन्फ़िगर करें.
  • Bazel 0.14.1 या इसके बाद का वर्शन इंस्टॉल करें. Docker सैंडबॉक्स की सुविधा, पुराने वर्शन में काम नहीं करती.
  • bazel-toolchains repo को अपनी बिल्ड की WORKSPACE फ़ाइल में जोड़ें. इसे रिलीज़ के सबसे नए वर्शन पर पिन किया गया है. इसके बारे में यहां बताया गया है.
  • इस सुविधा को चालू करने के लिए, अपनी .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 फ़्लैग की वैल्यू को, अपनी कस्टम कंटेनर इमेज के नाम से बदलें.

नेटिव तरीके से समस्या हल करना

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

हालांकि, इस तरीके से स्थानीय तौर पर इंस्टॉल किए गए टूल, बाइनरी, और डेटा आपके बिल्ड में लीक हो सकता है. ऐसा खास तौर पर तब होता है, जब यह configure-style WORKSPACE rules का इस्तेमाल करता है. इस तरह की लीक से रिमोट एक्ज़ीक्यूशन में समस्याएं आएंगी. इनका पता लगाने के लिए, 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 कंटेनर में समस्या हल करना

इस तरीके में, Bazel, होस्ट Docker कंटेनर के अंदर चलता है. साथ ही, Bazel की बिल्ड कार्रवाइयां, 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 डायरेक्ट्री को माउंट करती है. इससे Bazel को अन्य Docker कंटेनर बनाने और उन कंटेनर के साथ फ़ाइलें शेयर करने के लिए, /tmp के तहत मौजूद डायरेक्ट्री का इस्तेमाल करने की अनुमति मिलती है. आपका सोर्स कोड, कंटेनर में /src पर उपलब्ध है.

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

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

इसे टेस्ट करने के लिए, Docker कंटेनर में ये कमांड चलाएं:

docker ps
bazel version

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

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

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

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

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

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

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

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