संक्षेप में: नहीं, आपका VOLUME
निर्देश सही नहीं है।
डॉकरीफाइल VOLUME
निर्दिष्ट कंटेनर साइड वाले एक या अधिक संस्करणों को निर्दिष्ट करता है। लेकिन यह छवि लेखक को होस्ट पथ निर्दिष्ट करने की अनुमति नहीं देता है। होस्ट-साइड पर, डॉकर रूट के अंदर एक बहुत लंबे आईडी जैसे नाम के साथ वॉल्यूम बनाए जाते हैं। मेरी मशीन पर यह है /var/lib/docker/volumes
।
नोट: क्योंकि ऑटोजेनरेटेड नाम बहुत लंबा है और मानव के दृष्टिकोण से कोई मतलब नहीं है, इसलिए इन संस्करणों को अक्सर "अनाम" या "अनाम" कहा जाता है।
आपका उदाहरण जो 'का उपयोग करता है।' चरित्र मेरी मशीन पर भी नहीं चलेगा, चाहे मैं डॉट को पहला या दूसरा तर्क बनाऊं। मुझे यह त्रुटि संदेश मिला:
docker: डेमन से त्रुटि प्रतिक्रिया: oci रनटाइम त्रुटि: container_linux.go: 265: कंटेनर प्रक्रिया शुरू करने का कारण "process_linux.go: 368: कंटेनर इनट के कारण \" ओपन / डेव / ptmx: ऐसा कोई फ़ाइल या "निर्देशिका" नहीं है।
मुझे पता है कि क्या इस मुद्दे पर कहा गया है शायद किसी को समझने की कोशिश कर के लिए बहुत मूल्यवान नहीं है VOLUME
और -v
और यह निश्चित रूप से आप क्या हासिल करने की कोशिश के लिए एक समाधान प्रदान नहीं करता है। तो, उम्मीद है, निम्नलिखित उदाहरण इन मुद्दों पर कुछ और प्रकाश डालेंगे।
न्यूनतम: वॉल्यूम निर्दिष्ट करना
इस डॉकरफाइल को देखते हुए:
FROM openjdk:8u131-jdk-alpine
VOLUME vol1 vol2
(यदि हम निर्दिष्ट करते हैं vol1 vol2
या /vol1 /vol2
क्यों नहीं करते हैं , तो इस मिनिस्टीरियल के परिणाम से कोई फर्क नहीं पड़ता )
इसे बनाओ:
docker build -t my-openjdk
Daud:
docker run --rm -it my-openjdk
कंटेनर के अंदर, ls
कमांड लाइन में चलाएं और आप देखेंगे कि दो निर्देशिकाएं मौजूद हैं; /vol1
और /vol2
।
कंटेनर को चलाने से मेजबान की तरफ दो निर्देशिकाएं या "वॉल्यूम" भी बनते हैं।
कंटेनर चल रहा है, मेजबान मशीनdocker volume ls
पर निष्पादित करें और आपको कुछ इस तरह दिखाई देगा (मैंने नाम के मध्य भाग को तीन डॉट के साथ संक्षिप्तता के लिए बदल दिया है):
DRIVER VOLUME NAME
local c984...e4fc
local f670...49f0
वापस कंटेनर में , निष्पादित करें touch /vol1/weird-ass-file
(उक्त स्थान पर एक रिक्त फ़ाइल बनाता है)।
यह फ़ाइल अब होस्ट मशीन पर उपलब्ध है, अनाम संस्करणों में से एक में। इसने मुझे दो प्रयास किए क्योंकि मैंने पहली बार सूचीबद्ध वॉल्यूम की कोशिश की थी, लेकिन आखिरकार मैंने अपनी फ़ाइल को दूसरे सूचीबद्ध वॉल्यूम में पाया, मेजबान मशीन पर इस कमांड का उपयोग करते हुए:
sudo ls /var/lib/docker/volumes/f670...49f0/_data
इसी तरह, आप होस्ट पर इस फ़ाइल को हटाने का प्रयास कर सकते हैं और इसे कंटेनर में भी हटा दिया जाएगा।
नोट: _data
फ़ोल्डर को "माउंट बिंदु" के रूप में भी संदर्भित किया जाता है।
कंटेनर से बाहर निकलें और होस्ट पर वॉल्यूम को सूचीबद्ध करें। वे चले गए हैं। हमने --rm
कंटेनर चलाते समय ध्वज का उपयोग किया था और यह विकल्प प्रभावी रूप से न केवल कंटेनर को बाहर निकलने पर मिटा देता है, बल्कि वॉल्यूम भी।
एक नया कंटेनर चलाएं, लेकिन एक मात्रा का उपयोग करके निर्दिष्ट करें -v
:
docker run --rm -it -v /vol3 my-openjdk
यह एक तीसरा वॉल्यूम जोड़ता है और पूरे सिस्टम में तीन अनाम वॉल्यूम होते हैं। कमांड क्रैश हो गया होगा हम केवल निर्दिष्ट किया था -v vol3
। तर्क कंटेनर के अंदर एक पूर्ण पथ होना चाहिए । होस्ट-साइड पर, नया तीसरा वॉल्यूम गुमनाम है और अन्य दो संस्करणों के साथ रहता है ।/var/lib/docker/volumes/
यह पहले कहा गया था कि Dockerfile
एक होस्ट पथ पर मैप नहीं किया जा सकता है, जो रनटाइम के दौरान होस्ट से कंटेनर में फाइल लाने की कोशिश करते समय हमारे लिए एक समस्या पैदा करता है। एक अलग -v
सिंटैक्स इस समस्या को हल करता है।
कल्पना कीजिए ./src
कि मेरी परियोजना निर्देशिका में एक सबफ़ोल्डर है जिसे मैं /src
कंटेनर के अंदर सिंक करना चाहता हूं । यह आदेश चाल करता है:
docker run -it -v $(pwd)/src:/src my-openjdk
:
चरित्र के दोनों पक्षों को एक पूर्ण मार्ग की उम्मीद है। बाईं ओर मेजबान मशीन पर एक निरपेक्ष पथ है, दाएं तरफ कंटेनर के अंदर एक पूर्ण पथ है। pwd
एक कमांड है जो "वर्तमान / कार्यशील निर्देशिका को प्रिंट करता है"। $()
कोष्ठक के भीतर कमान ले जाने में कमांड डालते हुए , इसे एक उप-भाग में चलाता है और हमारी परियोजना निर्देशिका के लिए निरपेक्ष पथ को वापस लाता है।
यह सब एक साथ रखते हुए, मान लें कि ./src/Hello.java
हमारे प्रोजेक्ट फ़ोल्डर में हमारे पास मेजबान मशीन पर निम्नलिखित सामग्री है:
public class Hello {
public static void main(String... ignored) {
System.out.println("Hello, World!");
}
}
हम इस Dockerfile का निर्माण करते हैं:
FROM openjdk:8u131-jdk-alpine
WORKDIR /src
ENTRYPOINT javac Hello.java && java Hello
हम यह आदेश चलाते हैं:
docker run -v $(pwd)/src:/src my-openjdk
यह प्रिंट "हैलो, वर्ल्ड!"।
सबसे अच्छी बात यह है कि हम .java फ़ाइल को संशोधित करने के लिए पूरी तरह से स्वतंत्र हैं। दूसरे रन पर एक और आउटपुट के लिए एक नए संदेश के साथ - छवि के पुनर्निर्माण के बिना =)
अंतिम टिप्पणी
मैं डॉकटर के लिए काफी नया हूं, और उपरोक्त "ट्यूटोरियल" एक 3-दिन कमांड लाइन हैकॉन से एकत्रित जानकारी को दर्शाता है। मुझे लगभग शर्म आती है कि मैं अपने बयानों के समर्थन में अंग्रेजी जैसे दस्तावेज को साफ करने के लिए लिंक प्रदान करने में सक्षम नहीं हूं, लेकिन मुझे ईमानदारी से लगता है कि यह दस्तावेज की कमी और व्यक्तिगत प्रयास के कारण है। मुझे पता है कि उदाहरण मेरे वर्तमान सेटअप का उपयोग करके विज्ञापन के रूप में काम करते हैं जो "विंडोज 10 -> वैग्रांट 2.0.0 -> डॉकर 17.09.0-सीई" है।
ट्यूटोरियल इस समस्या को हल नहीं करता है कि "हम डॉकरफाइल में कंटेनर के पथ को कैसे निर्दिष्ट करें और रन कमांड को केवल होस्ट पथ निर्दिष्ट करें"। एक रास्ता हो सकता है, मुझे अभी नहीं मिला है।
अंत में, मुझे यह महसूस हो रहा है कि VOLUME
डॉकफाइल में निर्दिष्ट करना केवल असामान्य नहीं है, लेकिन यह शायद कभी उपयोग नहीं करने के लिए सबसे अच्छा अभ्यास है VOLUME
। दो कारणों से। पहला कारण जो हमने पहले ही पहचान लिया है: हम मेजबान पथ को निर्दिष्ट नहीं कर सकते हैं - जो कि एक अच्छी बात है क्योंकि डॉकएफ़ाइल्स एक मेजबान मशीन की बारीकियों के लिए बहुत ही अज्ञेय होना चाहिए। लेकिन दूसरा कारण यह है कि लोग --rm
कंटेनर चलाते समय विकल्प का उपयोग करना भूल सकते हैं । एक कंटेनर को हटाने के लिए याद कर सकते हैं लेकिन मात्रा को हटाने के लिए भूल जाते हैं। इसके अलावा, यहां तक कि सबसे अच्छी मानव स्मृति के साथ, यह पता लगाना एक कठिन काम हो सकता है कि सभी अनाम संस्करणों में से कौन सा सुरक्षित है।