इस समस्या के लगभग हर लेख में वॉल्यूम को दोष दिया जाता है, और ठीक इसी कारण सुधार में इतना समय लगता है। आपके पास एक bind mount था जो काम करता था, कॉर्पोरेट VPN जुड़ा, और docker compose up अब गायब source path, खाली डायरेक्टरी, या ऐसे mount के साथ विफल हो जाता है जिसे इंजन बनाने से मना कर देता है। जिन इकाइयों को मैंने साफ़ किया, उनमें Compose फ़ाइल नहीं बदली थी और पथ सही था। जो बदला वह यह था कि किस daemon को अनुरोध मिला, और mount त्रुटि बस वह पहली जगह थी जहाँ यह अंतर दिखाई दिया।

वॉल्यूम कभी नहीं हिला; अनुरोध हिला

एक -v /srv/app:/app फ़्लैग आपके shell द्वारा की जाने वाली डायरेक्टरी प्रतिलिपि नहीं है। क्लाइंट उसे API अनुरोध में बदलता है, और जो daemon उत्तर देता है वह /srv/app को अपनी स्वयं की फ़ाइल प्रणाली के सापेक्ष हल करता है। जब दोनों पक्ष एक ही kernel पर चलते हैं, तो वही पथ आपको फ़ाइल प्रबंधक में दिखता है। जब endpoint बदलता है, तो वही स्ट्रिंग ऐसी मशीन पर खोजी जाती है जिसने आपकी परियोजना डायरेक्टरी के बारे में कभी सुना नहीं, और daemon या तो source को गायब बताता है या चुपचाप उसकी जगह खाली डायरेक्टरी बना देता है।

इसी कारण नामित वॉल्यूम काम करता रहता है जबकि bind mount नहीं। -v appdata:/app daemon के स्वामित्व वाले स्टोरेज को नाम देता है, इसलिए किसी host path को किसी विशेष जगह मौजूद होने की आवश्यकता नहीं। अगर एक सेवा को bind mount से नामित वॉल्यूम में बदलने से त्रुटि गायब हो जाती है, तो आपने समस्या ठीक नहीं की। आपने पुष्टि की है कि क्लाइंट और daemon इस बात पर सहमत नहीं हैं कि पथ किस फ़ाइल प्रणाली का है, और वह मतभेद उसी क्षण लौट आता है जब आपको फिर से असली host डायरेक्टरी चाहिए।

mount को छूने से पहले endpoint प्रिंट करें

कई सेटिंग्स क्लाइंट को endpoint की ओर इंगित कर सकती हैं, और वे हमेशा सहमत नहीं होतीं: --context फ़्लैग, DOCKER_CONTEXT, DOCKER_HOST वर्तमान shell में, और क्लाइंट कॉन्फ़िगरेशन में सहेजा गया context। प्राथमिकता पर तर्क करने के बजाय, सभी को प्रिंट करें और उत्तरों की तुलना करें।

docker context show
docker context ls
docker version
docker info --format "{{.Name}} {{.OperatingSystem}} {{.ServerVersion}}"

क्लाइंट कॉन्फ़िग यहाँ रहता है: ~/.docker/config.json Linux और macOS पर, और यहाँ: %USERPROFILE%\.docker\config.json Windows पर, और वर्तमान टर्मिनल में export किया गया मान सहेजे गए मान को केवल उसी सत्र के लिए ओवरराइड करता है। अगर endpoint स्थानीय socket के बजाय hostname है, तो नाम-समाधान और रूट तय करते हैं कि वह कहाँ उतरेगा, और VPN क्लाइंट ठीक इन्हीं को फिर से लिखता है। जो tunnel कोई रूट जोड़ता है या resolver बदलता है, वह उस नाम को, जिसका अर्थ पहले यह लैपटॉप था, कॉर्पोरेट नेटवर्क के भीतर के पते पर भेज सकता है।

कॉन्फ़िगरेशन के बजाय स्थिति की तुलना करें। चलाएँ docker ps -a और docker images tunnel बंद रखकर, फिर दोबारा चालू रखकर। अलग कंटेनर सूची किसी भी कॉन्फ़िग फ़ाइल से अधिक मजबूत प्रमाण है, क्योंकि यह दिखाती है कि किसी दूसरे daemon ने आपके अनुरोध का उत्तर दिया।

daemon से पूछें कि क्या पथ वहाँ मौजूद है

जब आप जान जाएँ कि किस daemon तक पहुँचे, तो उसे डायरेक्टरी देखने दें। रूप --mount छोटे फ़्लैग की तुलना में स्पष्ट संदेश के साथ विफल होता है, क्योंकि यह कंटेनर शुरू करने से पहले source को सत्यापित करता है:

docker run --rm --mount type=bind,source=/srv/app,target=/app alpine ls -la /app

अगर यह source को गायब बताता है, तो इसे उस मशीन पर बनाएँ जिसने उत्तर दिया, या सेवा को नामित वॉल्यूम की ओर इंगित करें और डेटा वहाँ कॉपी करें। जो आपको नहीं करना चाहिए वह है इस जाँच से पहले वॉल्यूम फिर से बनाना और इंजन दोबारा इंस्टॉल करना। वे क्रियाएँ वातावरण को इतना बदल देती हैं कि असंगति छिप जाती है, जबकि वह अपनी जगह पर बनी रहती है।

एक और पथ पूरी तरह कहीं और चलता है: image खींचना daemon का काम है, क्लाइंट का नहीं। सफल खींच केवल यह सिद्ध करती है कि daemon किसी registry तक पहुँच सकता है, और काम करता bind mount केवल यह कि कोई पथ हल हुआ। हर पथ को वहीं जाँचें जहाँ वह वास्तव में निष्पादित होता है, वरना आप गलत पथ पर दोपहर बिताएँगे।

इंट्रानेट नाम दूसरे कारण से विफल होते हैं

उसी रिपोर्ट का दूसरा आधा आमतौर पर यह होता है कि कंटेनर intranet.corp.exampleतक नहीं पहुँच सकता। यह अलग तंत्र है, दूसरी वॉल्यूम समस्या नहीं। कंटेनर को अपना /etc/resolv.conf शुरू होते समय मिलता है, जो daemon resolver सेटिंग्स से उत्पन्न होता है, इसलिए कंटेनर बनने के बाद VPN द्वारा जोड़ा गया DNS सर्वर तब तक वहाँ नहीं दिखेगा जब तक कंटेनर फिर से न बने।

उपयोगकर्ता-परिभाषित नेटवर्क पर Docker का अंतर्निहित resolver बाहरी क्वेरी को host के कॉन्फ़िगर किए गए सर्वरों को भेजता है, जो तब मदद करता है जब VPN host resolver को फिर से लिखता है और नुकसान करता है जब split DNS कोई आंतरिक ज़ोन ऐसे सर्वर को भेजता है जिसे daemon अब नहीं देखता। संकीर्ण, स्पष्ट मैपिंग उन नामों के लिए बहस से बचती है जो कभी नहीं बदलते:

services:
  web:
    extra_hosts:
      - "intranet.corp.example:10.20.30.40"

यह कंटेनर की hosts फ़ाइल में एक प्रविष्टि लिखता है, इसलिए कंटेनर tunnel के बारे में कुछ नहीं सीखता, और यह पता भी जमा देता है। जब आंतरिक host हिलता है, तो प्रविष्टि तब तक गलत रहती है जब तक कोई Compose फ़ाइल संपादित न करे। इसे स्थिर उपकरण या पिन किए गए डेटाबेस के लिए उपयोग करें, और हिलते नामों को DNS को सौंप दें।

पुनः इंस्टॉल वास्तव में क्या बदलता है

Docker Desktop को फिर से इंस्टॉल करने से VM, socket और context सूची फिर से बनती है, और mount फिर से काम करने लगता है। वह परिणाम असली है और वह कुछ नहीं सिखाता, इसलिए अगले VPN अपडेट के बाद वही विफलता लौट आती है। पुनः इंस्टॉल ने वह endpoint बदल दिया जो क्लाइंट उपयोग कर रहा था; उसने आपकी परियोजना द्वारा नामित पथ को उस फ़ाइल प्रणाली से मेल नहीं कराया जिसे daemon वास्तव में पढ़ता है।

मेरा कार्य क्रम छोटा है। पुष्टि करें कि क्लाइंट कौन सा endpoint उपयोग करेगा। कंटेनर सूचियों की तुलना करके पुष्टि करें कि किस daemon ने उत्तर दिया। उस daemon से source path सूचीबद्ध करने को कहें। तभी mount संपादित करें, hosts प्रविष्टि जोड़ें, या वॉल्यूम प्रकार बदलें। अगर आप VPN पर काम करने वाली टीम के लिए Compose फ़ाइल बनाए रखते हैं, तो उन डेटा के लिए नामित वॉल्यूम पसंद करें जिनका स्वामित्व daemon के पास होना चाहिए, ताकि host path कभी अनुबंध का हिस्सा न बने।

संबंधित लेख