डॉकर में "उजागर" और "प्रकाशित" के बीच अंतर क्या है?


517

मैं Dockerfiles के साथ प्रयोग कर रहा हूं, और मुझे लगता है कि मैं अधिकांश तर्क को समझता हूं। हालाँकि, मुझे इस संदर्भ में "उजागर" और "प्रकाशन" के बीच का अंतर नहीं दिख रहा है।

मैंने पहले देखे गए सभी ट्यूटोरियल्स EXPOSEको Dockerfile में कमांड शामिल किया है :

...
EXPOSE 8080
...

वे तब इस डॉकरीफाइल से एक छवि बनाते हैं:

$ docker build -t an_image - < Dockerfile

और फिर छवि को चलाते समय उसी पोर्ट को ऊपर प्रकाशित करें:

$ docker run -d -p 8080 an_image

या सभी पोर्ट का उपयोग करके प्रकाशित करें

$ docker run -d -P an_image

डॉकरफाइल में एक बंदरगाह को उजागर करने का क्या मतलब है, अगर इसे वैसे भी प्रकाशित किया जाएगा? क्या पहले कभी किसी पोर्ट को उजागर करने की आवश्यकता होगी, और बाद में इसे प्रकाशित नहीं करने की? प्रभावी रूप से, मैं उन सभी पोर्ट्स को निर्दिष्ट करना चाहूंगा, जिनका उपयोग मैं डॉकरीफाइल में छवि बनाने के दौरान करूंगा, और फिर उनके साथ फिर से परेशान न करें, उन्हें बस के साथ चलाएं:

$ docker run -d an_image

क्या यह संभव है?

जवाबों:


731

मूल रूप से, आपके पास तीन विकल्प हैं:

  1. न तो निर्दिष्ट करें EXPOSEऔर न ही-p
  2. केवल निर्दिष्ट करें EXPOSE
  3. निर्दिष्ट करें EXPOSEऔर-p

1) यदि आप न तो निर्दिष्ट करते हैं और न EXPOSEही -p, कंटेनर में सेवा केवल कंटेनर के अंदर से ही सुलभ होगी ।

2) यदि आप EXPOSEपोर्ट करते हैं, तो कंटेनर में सेवा डॉकर के बाहर से नहीं, बल्कि अन्य डॉकटर कंटेनर के अंदर से पहुंच सकती है। तो यह अंतर-कंटेनर संचार के लिए अच्छा है।

3) यदि आप EXPOSEऔर -pएक बंदरगाह, कंटेनर में सेवा कहीं से भी सुलभ है, डॉकर के बाहर भी।

दोनों के अलग होने का कारण IMHO है क्योंकि:

  • होस्ट पोर्ट चुनना मेजबान पर निर्भर करता है और इसलिए डॉकफाइल से संबंधित नहीं है (अन्यथा यह होस्ट के आधार पर होगा),
  • और अक्सर यह पर्याप्त होता है यदि एक कंटेनर में एक सेवा अन्य कंटेनरों से सुलभ हो।

प्रलेखन स्पष्ट रूप से कहा:

EXPOSEअनुदेश लिंक भीतर उपयोग के लिए बंदरगाहों को उजागर करता है।

यह आपको कंटेनरों को जोड़ने के लिए भी इंगित करता है , जो मूल रूप से अंतर-कंटेनर संचार है जिसके बारे में मैंने बात की थी।

पुनश्च: यदि आप करते हैं -p, लेकिन नहीं करते हैं EXPOSE, तो डॉकर एक निहित कार्य करता है EXPOSE। ऐसा इसलिए है क्योंकि यदि कोई पोर्ट जनता के लिए खुला है, तो यह स्वचालित रूप से अन्य डॉकटर कंटेनरों के लिए भी खुला है। इसलिए -pशामिल हैं EXPOSE। इसलिए मैंने इसे चौथे मामले के रूप में ऊपर सूचीबद्ध नहीं किया है।


57
मुझे लगता है कि आप EXPOSE के साथ सही नहीं हैं। अन्य कंटेनरों से, आप उन्हें उजागर किए बिना सभी कंटेनर बंदरगाहों तक पहुंच सकते हैं। मैंने वो कोशिश की। यहाँ पकड़ यह है कि कंटेनर आईपी पता अप्रत्याशित है। मेरा मानना ​​है कि लिंक का उपयोग उस कंटेनर को निर्दिष्ट करने के लिए किया जाता है जिसे आप कनेक्ट करना चाहते हैं (इसलिए आप विशिष्ट कंटेनर आईपी से लिंक करते हैं), कनेक्शन को सक्षम करने के लिए नहीं।
जिरी

7
"यदि आप उन में से किसी को निर्दिष्ट नहीं करते हैं", तो उपयोगी होगा यदि आपने स्पष्ट किया कि "उन" से आपका मतलब है EXPOSEऔर -pतीन बुलेट पॉइंट्स अप्रत्यक्ष नहीं हैं। मुझे वहाँ थोड़ा भ्रमित हो गया।
पिथिकोस

4
पूरी तरह से पूरा हो सके, यह जवाब भी एक चौथाई संभव मामले ध्यान देना चाहिए: आप निर्दिष्ट नहीं किया है EXPOSE, लेकिन आप था निर्दिष्ट -p। यह मेरी समझ है कि यदि आप हमेशा उपयोग -pऔर व्यक्तिगत कंटेनर चलाने तो EXPOSEछोड़ देना ठीक है, लेकिन जब का उपयोग कर इसे उपयोगी / आवश्यक हो जाता है -Pया --link। (और जब से आप नहीं जानते कि अन्य लोग आपकी छवि का उपयोग कैसे करेंगे, EXPOSEकिसी भी सार्वजनिक चित्र में निर्दिष्ट किया जाना चाहिए।)
ग्रैंडऑपनर

6
डॉक्स अब नहीं बताता है "एक्सपोजर निर्देश लिंक के भीतर उपयोग के लिए बंदरगाहों को उजागर करता है"।
लोरिन होचस्टीन

11
डाउनवोट क्योंकि यह काफी गलत है। एक्सपोज़ मूल रूप से दस्तावेज़ीकरण है, और इसका उपयोग नहीं करने से पहुंच प्रतिबंधित नहीं होती है। यह एक डेंजरस गलतफहमी है यदि कोई इस तक पहुंच को सीमित करने के लिए निर्भर करता है।
mc0e

166

संक्षिप्त जवाब:

  • EXPOSEदस्तावेजीकरण का एक तरीका है
  • --publish(या -p) एक होस्ट पोर्ट को रनिंग कंटेनर पोर्ट पर मैप करने का एक तरीका है

उसके नीचे सूचना:

  • EXPOSEDockerfiles( दस्तावेजीकरण ) से संबंधित है
  • --publishसे संबंधित है docker run ...( निष्पादन / रन-टाइम )

एक्सपोजिंग और प्रकाशन पोर्ट

डॉकर नेटवर्किंग में, दो अलग-अलग तंत्र हैं जो सीधे नेटवर्क पोर्ट को शामिल करते हैं: पोर्ट को उजागर करना और प्रकाशित करना। यह डिफ़ॉल्ट ब्रिज नेटवर्क और उपयोगकर्ता द्वारा परिभाषित ब्रिज नेटवर्क पर लागू होता है।

  • आप EXPOSEDockerfile में कीवर्ड का उपयोग करके पोर्ट्स को उजागर करते हैं और --exposeफ्लैग टू डूकर रन करते हैं। एक्सपोज़िंग पोर्ट एक तरह से डॉक्यूमेंटिंग है कि किन पोर्ट्स का उपयोग किया जाता है, लेकिन वास्तव में कोई भी पोर्ट मैप या ओपन नहीं करता है । एक्सपोजिंग पोर्ट वैकल्पिक है।

  • आप पोर्ट को --publishया --publish-allध्वज का उपयोग करके प्रकाशित करते हैं docker run। यह डॉकटर को बताता है कि कंटेनर के नेटवर्क इंटरफेस पर कौन से पोर्ट खोलने हैं। जब कोई पोर्ट प्रकाशित होता है, तो इसे 30000होस्ट मशीन पर उपलब्ध उच्च-ऑर्डर पोर्ट (उच्चतर ) में मैप किया जाता है , जब तक कि आप पोर्ट को रनटाइम पर होस्ट मशीन पर मैप करने के लिए निर्दिष्ट नहीं करते हैं। आप पोर्ट को होस्ट मशीन पर मैप करने के लिए निर्दिष्ट नहीं कर सकते हैं जब आप छवि का निर्माण करते हैं (डॉकफेराइल में), क्योंकि यह गारंटी देने का कोई तरीका नहीं है कि पोर्ट होस्ट मशीन पर उपलब्ध होगा जहां आप छवि चलाते हैं

से: डॉकर कंटेनर नेटवर्किंग

अद्यतन अक्टूबर 2019 : पाठ का उपरोक्त टुकड़ा अब डॉक्स में नहीं है, लेकिन एक संग्रहीत संस्करण यहां है: docs.docker.com/v17.09/engine/userguide/networking/#exposing-and-publisherport

शायद वर्तमान प्रलेखन नीचे है:

प्रकाशित पोर्ट

डिफ़ॉल्ट रूप से, जब आप एक कंटेनर बनाते हैं, तो वह इसके किसी भी पोर्ट को बाहरी दुनिया में प्रकाशित नहीं करता है। किसी पोर्ट को डॉकर के बाहर, या डॉकरी कंटेनरों के लिए उपलब्ध कराने के लिए, जो कंटेनर के नेटवर्क से कनेक्ट नहीं हैं, --publishया -pध्वज का उपयोग करें । यह एक फ़ायरवॉल नियम बनाता है जो डॉकेर होस्ट पर पोर्ट में कंटेनर पोर्ट को मैप करता है।

और यहाँ पाया जा सकता है: docs.docker.com/config/containers/container-networking/#publisher-ports

इसके अलावा,

बेनकाब

... EXPOSEनिर्देश वास्तव में पोर्ट प्रकाशित नहीं करता है । यह एक प्रकार के प्रलेखन के रूप में कार्य करता है छवि बनाने वाले व्यक्ति और कंटेनर चलाने वाले व्यक्ति के बीच , जिसके बारे में बंदरगाहों को प्रकाशित करने का इरादा है।

से: Dockerfile संदर्भ






सेवा का उपयोग कर सकते हैं जब EXPOSE/ --publishपरिभाषित नहीं कर रहे हैं:

@ गोलो रोडेन के जवाब में कहा गया है कि ::

"यदि आप उनमें से किसी को भी निर्दिष्ट नहीं करते हैं, तो कंटेनर में सेवा कंटेनर के अंदर के अलावा कहीं से भी सुलभ नहीं होगी।"

हो सकता है कि उस समय ऐसा था जब उत्तर लिखा जा रहा था, लेकिन अब ऐसा लगता है कि भले ही आप उपयोग न करें EXPOSEया --publish, hostऔर containersउसी नेटवर्क के अन्य आप उस कंटेनर के अंदर शुरू होने वाली सेवा तक पहुंच सकते हैं।

इसका परीक्षण कैसे करें:

मैंने निम्नलिखित प्रयोग किया है Dockerfile। असल में, मैं ubuntu के साथ शुरू करता हूं और एक छोटा वेब सर्वर स्थापित करता हूं:

FROM ubuntu
RUN apt-get update && apt-get install -y mini-httpd

मैं build"टेस्टएक्सपोज" के रूप में छवि और runएक नया कंटेनर के साथ:

docker run --rm -it testexpose bash

कंटेनर के अंदर, मैं कुछ उदाहरण प्रस्तुत करता हूं mini-httpd:

root@fb8f7dd1322d:/# mini_httpd -p 80
root@fb8f7dd1322d:/# mini_httpd -p 8080
root@fb8f7dd1322d:/# mini_httpd -p 8090

फिर मैं curlमेजबान या अन्य कंटेनरों से होम पेज लाने के लिए उपयोग करने में सक्षम हूं mini-httpd


16
यह अब सही उत्तर है। स्वीकृत उत्तर पूर्व संस्करणों पर आधारित है, ऐसा लगता है।
ल्यूक डब्ल्यू

होस्ट पोर्ट क्या है जिसका उपयोग आपने कर्ल के लिए किया है?
दिमागी तूफान

मैंने कंटेनर के आईपी (जैसे कुछ 172.17.0.2) और उन सभी बंदरगाहों का उपयोग किया है जिनका मैं उल्लेख कर रहा हूं। यदि आप मैक / विंडोज के लिए डॉकर का उपयोग कर रहे हैं, तो नेटवर्किंग अलग है। कोई docker0पुल नहीं है।
tgogos

जब "EXP" ध्वज के साथ सभी EXPOSEd पोर्ट प्रकाशित करते हैं, तो मैं यह कैसे बता सकता हूं कि होस्ट पर किस पोर्ट का उपयोग किया जाता है ??
साठ4


9

आधिकारिक दस्तावेज़ीकरण संदर्भ देखें: https://docs.docker.com/engine/reference/builder/#expose

यदि आप कंटेनर के साथ EXPOSEचल रहे हैं तो कंटेनर के चलने के लिए छवि निर्माण समय पर निजी (कंटेनर) और सार्वजनिक (होस्ट) पोर्ट को परिभाषित करने की अनुमति दें -P

$ docker help run
...
  -P, --publish-all                    Publish all exposed ports to random ports
...

सार्वजनिक पोर्ट और प्रोटोकॉल वैकल्पिक हैं, यदि सार्वजनिक पोर्ट निर्दिष्ट नहीं है, तो डॉकर द्वारा निर्दिष्ट कंटेनर पोर्ट को बेनकाब करने के लिए डॉकटर द्वारा होस्ट पर एक यादृच्छिक पोर्ट का चयन किया जाएगा।

एक अच्छा विकल्प सार्वजनिक पोर्ट निर्दिष्ट नहीं करता है, क्योंकि यह प्रति होस्ट केवल एक कंटेनर को सीमित करता है (एक दूसरा कंटेनर पहले से उपयोग में आने वाले पोर्ट को फेंक देगा)।

आप उपयोग कर सकते हैं -pमें docker runनियंत्रित करने के लिए क्या सार्वजनिक बंदरगाह उजागर कंटेनर बंदरगाहों कनेक्शन हो जाएगा।

वैसे भी, यदि आप EXPOSE( -Pdocker run के साथ) उपयोग नहीं करते हैं और न ही -p, कोई पोर्ट उजागर नहीं किया जाएगा।

यदि आप हमेशा उपयोग -pकरते docker runहैं तो आपको ज़रूरत नहीं है EXPOSEलेकिन यदि आप EXPOSEअपने docker runआदेश का उपयोग करते हैं तो अधिक सरल हो सकता है, EXPOSEउपयोगी हो सकता है यदि आप परवाह नहीं करते हैं कि मेजबान पर क्या पोर्ट एक्सपोज़ किया जाएगा, या यदि आप सुनिश्चित हैं कि केवल एक कंटेनर लोड किया जाएगा।


यह सही है। जब आपके पास Dockerfile में EXPOSE पोर्टनंबर है, तो -P के साथ डॉक रन को लागू करना याद रखें।
कुनयू त्वाई

6

आप Dockerfile में EXPOSE कीवर्ड का उपयोग करके पोर्ट्स को एक्सपोज करते हैं या - doix रन को -पोस्ट फ्लैग करते हैं। एक्सपोज़िंग पोर्ट एक तरह से डॉक्यूमेंटेशन होता है कि किन पोर्ट्स का उपयोग किया जाता है, लेकिन वास्तव में कोई भी पोर्ट मैप या ओपन नहीं करता है। एक्सपोजिंग पोर्ट वैकल्पिक है।

स्त्रोत: जीथब कमिट


3

ज्यादातर लोग नेटवर्क के साथ डॉक कंपोज करते हैं। प्रलेखन कहता है:

डॉकर नेटवर्क सुविधा नेटवर्क के भीतर बंदरगाहों को उजागर करने की आवश्यकता के बिना नेटवर्क बनाने का समर्थन करती है, विस्तृत जानकारी के लिए इस सुविधा का अवलोकन देखें)।

जिसका अर्थ है कि यदि आप कंटेनरों के बीच संचार के लिए नेटवर्क का उपयोग करते हैं, तो आपको बंदरगाहों को उजागर करने की चिंता करने की आवश्यकता नहीं है।


-5

EXPOSE का उपयोग स्थानीय पोर्ट कंटेनर पोर्ट को मैप करने के लिए किया जाता है: यदि आप निर्दिष्ट करते हैं जैसे docker file में एक्सपोज़ करें

EXPOSE 8090

क्या करता है यह लोकलहोस्ट पोर्ट 8090 को कंटेनर पोर्ट 8090 में मैप करेगा

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.