मैं डॉकटर कंटेनरों के बीच संबंध कैसे स्थापित करूं ताकि पुनः आरंभ करने से यह टूट न जाए?


80

मेरे पास कुछ डॉकटर कंटेनर हैं जैसे:

  • nginx
  • वेब ऐप 1
  • वेब ऐप 2
  • PostgreSQL

चूंकि Nginx को वेब एप्लिकेशन 1 और 2 के अंदर वेब एप्लिकेशन सर्वर से कनेक्ट करने की आवश्यकता होती है, और वेब ऐप्स को PostgreSQL से बात करने की आवश्यकता होती है, मेरे पास इस तरह के लिंक हैं:

  • Nginx --- लिंक ---> वेब ऐप 1
  • Nginx --- लिंक ---> वेब ऐप 2
  • वेब ऐप 1 --- लिंक ---> PostgreSQL
  • वेब ऐप 2 --- लिंक ---> पोस्टग्रेक्यूएल

यह पहली बार में बहुत अच्छा काम करता है। हालाँकि, जब मैं वेब ऐप 1 और वेब ऐप 2 का नया संस्करण विकसित करता हूं, तो मुझे उन्हें बदलने की आवश्यकता है। मैं जो भी करता हूं वह वेब ऐप कंटेनरों को हटा देता है, नए कंटेनर सेट करता है और उन्हें शुरू करता है।

वेब एप्लिकेशन कंटेनरों के लिए, पहली बार में उनके आईपी पते कुछ इस तरह होंगे:

  • 172.17.0.2
  • 172.17.0.3

और उनके बदलने के बाद, उनके पास नए आईपी पते होंगे:

  • 172.17.0.5 है
  • 172.17.0.6

अब, नगीनेक्स कंटेनर में उन पर्यावरण के चर अब भी पुराने आईपी पते की ओर इशारा कर रहे हैं। यहाँ समस्या आती है। मैं कंटेनरों के बीच संबंध को तोड़े बिना कंटेनर को कैसे बदलूं? यही मुद्दा PostgreSQL का भी होगा। अगर मुझे PostgreSQL छवि संस्करण को अपग्रेड करना है, तो मुझे निश्चित रूप से इसे हटाने और नए को चलाने की आवश्यकता है, लेकिन फिर मुझे पूरे कंटेनर ग्राफ को फिर से बनाने की आवश्यकता है, इसलिए यह वास्तविक जीवन सर्वर ऑपरेशन के लिए आदर्श नहीं है।

जवाबों:


53

का प्रभाव --linkस्थिर है, इसलिए यह आपके परिदृश्य के लिए काम नहीं करेगा (वर्तमान में कोई पुन: लिंकिंग नहीं है, हालांकि आप लिंक हटा सकते हैं )।

हम लिंक या एंबेसडर के बिना (हालांकि आप एंबेसडर भी जोड़ सकते हैं) इसे हल करने के लिए dockerize.it पर दो अलग-अलग तरीकों का उपयोग कर रहे हैं।

1) डायनेमिक डीएनएस का उपयोग करें

सामान्य विचार यह है कि आप अपने डेटाबेस (या किसी अन्य सेवा) के लिए एक ही नाम निर्दिष्ट करते हैं और कंटेनरों को शुरू करने और रोकने के लिए वास्तविक आईपी के साथ एक अल्पकालिक DNS सर्वर को अपडेट करते हैं।

हमने शुरुआत की स्काईडॉक शुरुआत की । यह दो डॉकटर कंटेनरों, डीएनएस सर्वर और एक मॉनिटर के साथ काम करता है जो इसे स्वचालित रूप से अपडेट रखता है। बाद में हम और अधिक कस्टम का उपयोग कर कुछ के लिए ले जाया कौंसुल (: यह भी एक dockerized संस्करण का उपयोग कर डोकर-वाणिज्य दूत )।

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

2) डॉक ब्रिज आईपी का उपयोग करें

कंटेनर पोर्ट को उजागर करते समय आप उन्हें docker0पुल से बांध सकते हैं , जिसमें एक प्रसिद्ध पता है (या हो सकता है)।

एक नए संस्करण के साथ एक कंटेनर को प्रतिस्थापित करते समय, बस नए कंटेनर को समान आईपी पर समान पोर्ट प्रकाशित करें।

यह सरल है, लेकिन अधिक सीमित भी है। यदि आपके पास समान सॉफ़्टवेयर चलाते हैं (उदाहरण के लिए, दो कंटेनर docker0पुल पर 3306 पोर्ट पर नहीं सुन सकते हैं ), इत्यादि…


20

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

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

1) नया नेटवर्क बनाएं

$ docker network create <network-name>       

2) कंटेनरों को नेटवर्क से कनेक्ट करें

$ docker run --net=<network-name> ...

या

$ docker network connect <network-name> <container-name>

3) पिंग कंटेनर नाम से

docker exec -ti <container-name-A> ping <container-name-B> 

64 bytes from c1 (172.18.0.4): icmp_seq=1 ttl=64 time=0.137 ms
64 bytes from c1 (172.18.0.4): icmp_seq=2 ttl=64 time=0.073 ms
64 bytes from c1 (172.18.0.4): icmp_seq=3 ttl=64 time=0.074 ms
64 bytes from c1 (172.18.0.4): icmp_seq=4 ttl=64 time=0.074 ms

प्रलेखन के इस भाग को देखें ;

नोट: विरासत linksके विपरीत नई नेटवर्किंग पर्यावरण चर नहीं बनाएगी, न ही अन्य कंटेनरों के साथ पर्यावरण चर साझा करेगी

यह सुविधा वर्तमान में उपनामों का समर्थन नहीं करती है


मैं केवल 1.9 या बाद के संस्करण में काम करना चाहता हूं। कुछ वितरण अभी तक नवीनतम के साथ जारी नहीं किए गए हैं।
16:35 पर जॉन गिओटा

एक अन्य विकल्प कंटेनर के नाम के बजाय नेटवर्क-स्कोप्ड उर्फ ​​का उपयोग करना है (जिसे विश्व स्तर पर अद्वितीय होना हमेशा अच्छा नहीं होता है)। लेकिन जवाब फिर भी बिल्कुल सही है।
इवान अनिशचुक

10

आप एक राजदूत कंटेनर का उपयोग कर सकते हैं । लेकिन राजदूत कंटेनर को अपने क्लाइंट से लिंक न करें, क्योंकि यह ऊपर की तरह ही समस्या पैदा करता है। इसके बजाय, docker होस्ट (आमतौर पर 172.17.42.1) पर राजदूत कंटेनर के उजागर पोर्ट का उपयोग करें। उदाहरण:

पोस्टग्रेज वॉल्यूम:

$ docker run --name PGDATA -v /data/pgdata/data:/data -v /data/pgdata/log:/var/log/postgresql phusion/baseimage:0.9.10 true

पोस्टग्रैज-कंटेनर:

$ docker run -d --name postgres --volumes-from PGDATA -e USER=postgres -e PASS='postgres' paintedfox/postgresql

पदकों के लिए राजदूत-कंटेनर:

$ docker run -d --name pg_ambassador --link postgres:postgres -p 5432:5432 ctlc/ambassador

अब आप एंबेसडर कंटेनर को लिंक किए बिना एक पोस्टग्रेजल क्लाइंट कंटेनर शुरू कर सकते हैं और गेटवे होस्ट (आमतौर पर 172.17.42.1) पर पोस्टग्रेजल एक्सेस कर सकते हैं:

$ docker run --rm -t -i paintedfox/postgresql /bin/bash
root@b94251eac8be:/# PGHOST=$(netstat -nr | grep '^0\.0\.0\.0 ' | awk '{print $2}')
root@b94251eac8be:/# echo $PGHOST
172.17.42.1
root@b94251eac8be:/#
root@b94251eac8be:/# psql -h $PGHOST --user postgres
Password for user postgres: 
psql (9.3.4)
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)
Type "help" for help.

postgres=#
postgres=# select 6*7 as answer;
 answer 
--------
     42
(1 row)

bpostgres=# 

अब आप ग्राहक को पुनः आरंभ करने के लिए राजदूत कंटेनर को फिर से शुरू कर सकते हैं।


"-p 5432: 5432" बाहरी दुनिया के लिए PostgreSQL को उजागर नहीं करता है?
फेंग-पेन लिन

2
हाँ यह होगा। यदि आप यह नहीं चाहते हैं, तो आप "-p 172.17.42.1:5432:5432" का उपयोग कर सकते हैं।
स्वेन थम्मलर

1
वैसे, आपको "पीजीडीटीए" कंटेनर बनाने और इसे पोस्टग्रेसल कंटेनर से लिंक करने की आवश्यकता क्यों है? मुझे समझ नहीं आ रहा है, क्यों न सिर्फ पोस्टग्रैसक कंटेनर बनाएं, और इसकी मात्रा को सीधे एक मेजबान निर्देशिका में मैप करें?
फेंग-पेन लिन

PGDATA कंटेनर की जरूरत नहीं है, मैं इसका इस्तेमाल सिर्फ चिंताओं को अलग करने के लिए करता हूं। पॉज़र्स कंटेनर शुरू करते समय मुझे यह याद रखने की ज़रूरत नहीं है कि पीजीडीएटीए कंटेनर में वॉल्यूम कैसे मैप किए जाते हैं। मैंने इसे जोड़ा है क्योंकि मैं वर्तमान में यह कर रहा हूं। यह मूल रूप से स्वाद की बात है - मैं खुद अभी तक निश्चित नहीं हूं कि यह एक अच्छा विचार है या नहीं ...
स्वेन थुम्मलर

स्वेन की तरह डेटा वॉल्यूम कंटेनर का उपयोग करना वास्तव में सबसे अच्छा अभ्यास है।
derFunk

2

यदि कोई अभी भी उत्सुक है, तो आपको प्रत्येक डॉक कंटेनर के होस्ट आदि / / होस्ट्स फ़ाइल में उपयोग करना होगा और ईएनवी चर पर निर्भर नहीं होना चाहिए क्योंकि वे स्वचालित रूप से अपडेट नहीं होते हैं।

लिंक किए गए कंटेनर में से प्रत्येक के लिए एक होस्ट फ़ाइल प्रविष्टि होगी, जो कि LINKEDCONTAINERNAME_PORT_PORTNUMBER_T_T आदि प्रारूप में है।

निम्नलिखित docker डॉक्स से है

डॉकर पर्यावरण चर पर महत्वपूर्ण नोट

/ Etc / मेजबान फ़ाइल में होस्ट प्रविष्टियों के विपरीत, स्रोत कंटेनर को पुनरारंभ किए जाने पर पर्यावरण चर में संग्रहीत आईपी पते स्वचालित रूप से अपडेट नहीं होते हैं। हम लिंक किए गए कंटेनरों के आईपी पते को हल करने के लिए / etc / मेजबान में मेजबान प्रविष्टियों का उपयोग करने की सलाह देते हैं।

ये पर्यावरण चर केवल कंटेनर में पहली प्रक्रिया के लिए निर्धारित किए जाते हैं। कुछ डेमॉन, जैसे sshd, जब कनेक्शन के लिए गोले खोलते हैं, तो उन्हें साफ़ कर देगा।


2

यह 3 सप्ताह पहले डॉक के प्रायोगिक निर्माण में शामिल है, सेवाओं की शुरूआत के साथ: https://github.com/docker/docker/blob/master/experimental/networking.md

आपको --publish-service <name>तर्कों के साथ डॉकटर कंटेनर चलाकर एक गतिशील लिंक प्राप्त करने में सक्षम होना चाहिए । यह नाम डीएनएस के माध्यम से सुलभ होगा। यह कंटेनर रीस्टार्ट पर स्थिर है (जब तक आप कंटेनर को उसी सेवा नाम के साथ पुनरारंभ करते हैं जो निश्चित रूप से है)


आप उस संस्करण को कैसे स्थापित करते हैं? github.com/docker/docker/releases/tag/v1.8.0-rc1
m59

1
अधिक जानकारी के लिए इस पृष्ठ को देखें: github.com/docker/docker/tree/master/experimental । लघु संस्करण: wget -qO- https://experimental.docker.com/ | shप्रायोगिक संस्करण को स्थापित करने के लिए चलाएं
लॉरेंस रिटवेल्ड

1
यह उत्तर मान्य था लेकिन अब आउटडेटेड प्रायोगिक publish-serviceविकल्प के रूप में पुराना है। अब उनके पास इसके बजाय नेटवर्क-स्कोप्ड उपनाम हैं। अनिवार्य रूप से हालांकि एक ही बात है।
इवान अनिशचुक

1

आप इसे हल करने के लिए नामों के साथ dockerlinks का उपयोग कर सकते हैं ।

सबसे बुनियादी सेटअप पहले एक नामित डेटाबेस कंटेनर बनाना होगा :

$ sudo docker run -d --name db training/postgres

तब db से कनेक्ट करने वाला एक वेब कंटेनर बनाएं:

$ sudo docker run -d -P --name web --link db:db training/webapp python app.py

इसके साथ, आपको कंटेनरों को अपने आईपी एड्रेस के साथ मैन्युअल रूप से कनेक्ट करने की आवश्यकता नहीं है।


2
हम्म ... ऐसा लगता है कि docker किसी तरह आपके लिए लिंक्ड होस्टनाम उत्पन्न करेगा, लेकिन जिस तरह से यह करता है, वह / etc / host में नाम उत्पन्न करता है, यह स्थिर है, जब मैं लिंक किए गए कंटेनर को पुनरारंभ करता हूं, तो IP बदल जाता है, लेकिन / आदि। / मेजबान वही रहते हैं, इसलिए यह काम नहीं करेगा।
फंग-पेन लिन

2
चूंकि डॉकर संस्करण 1.0 आईपी पते को निर्दिष्ट करने के लिए अधिक आक्रामक है। जब आप एक कंटेनर को पुनः आरंभ करते हैं ( dbइस मामले में) तो उसे एक नया आईपी पता प्राप्त होगा। आपके अन्य कंटेनर (पुनः आरंभ या नहीं) उस समय से ईएनवी मूल्यों को बनाए रखेगा, जब आपने इसे लॉन्च किया था और यह बेकार है।
जर्मनडज

1
fyi ऐसा लगता है कि एक फिक्स आ रहा है, / etc / होस्ट तब अपडेट किए जाएंगे जब एक लिंक किए गए कंटेनर को पुनः आरंभ किया जाएगा: github.com/docker/docker/issues/6350
jamshid

1
यह मुद्दा तय हो गया है और प्रस्तावित पद्धति मेरे लिए काम कर रही है।
जेन्स पीगा

1
यह यहाँ सबसे सही उत्तर है। एकमात्र समस्या लिंक लिंक यूनिडायरेक्शनल है और कंटेनर के बीच एक निर्भरता जोड़ता है: आप दो कंटेनरों को क्रॉस-लिंक नहीं कर सकते हैं और आप लिंक किए गए कंटेनर को रोक नहीं सकते हैं और फिर इसे फिर से शुरू कर सकते हैं (नए विकल्प या कुछ के साथ)। उनमें से किसी भी मामले में, नेटवर्क का उपयोग करें (और या तो net-aliasया कंटेनर नाम)।
इवान अनिशचुक

1

OpenSVC दृष्टिकोण के साथ, आप इसके द्वारा हल कर सकते हैं:

  • अपने खुद के आईपी पते / डीएनएस नाम के साथ एक सेवा का उपयोग करें (आपके अंतिम उपयोगकर्ता कनेक्ट होंगे)
  • डॉकटर को बंदरगाहों को इस विशिष्ट आईपी पते ("--आईपी" डॉकटर विकल्प) को उजागर करने के लिए कहें
  • सेवा आईपी पते से कनेक्ट करने के लिए अपने एप्लिकेशन कॉन्फ़िगर करें

हर बार जब आप एक कंटेनर की जगह लेते हैं, तो आपको यकीन है कि यह सही आईपी पते से जुड़ जाएगा।

यहाँ ट्यूटोरियल => ओपनएसवीसी के साथ डॉकटर मल्टी कंटेनर

टुटो के अंत में "जटिल ऑर्केस्ट्रेशन" भाग को याद न करें, जो कंटेनरों को सही क्रम में शुरू करने / रोकने में मदद कर सकते हैं (1 पोस्टग्रैस्कल सबसेट + 1 वेबैप सबसेट + 1 नगनेक्स सबसेट)

मुख्य दोष यह है कि आप जनता के पते पर वेबएप और पोस्टग्रेक्यूएल पोर्ट्स को उजागर करते हैं, और वास्तव में केवल नगनेक्स टीसीपी पोर्ट को सार्वजनिक रूप से उजागर करने की आवश्यकता होती है।


1

आप लिंक को अक्षुण्ण बनाए रखने के लिए एक मध्यस्थ कंटेनर होने की राजदूत विधि भी आजमा सकते हैं ... ( अधिक जानकारी के लिए https://docs.docker.com/articles/ambassador_pattern_linking/ देखें )


राजदूत एक अच्छा पैटर्न है फिर भी यह एक ही समस्या से ग्रस्त है: आईपी पते को पुनरारंभ करने पर जरूरी अपडेट नहीं किया जाएगा। वे हालांकि अंतर-मेजबान कनेक्टिविटी के लिए महान हैं। ठीक है, हो सकता है कि नए डॉकटर रिलीज के साथ की जरूरत नहीं होगी।
इवान अनिशचुक

@ इवानअंशुक सच है, लेकिन जिस समय यह टिप्पणी की गई थी, यह जाने का रास्ता था ... (+2 साल पहले;))
गेकी

0

आप अपनी छवियों के कनेक्शन पोर्ट को होस्ट पर निर्धारित पोर्ट से बांध सकते हैं और इसके बजाय उनका उपयोग करने के लिए सेवाओं को कॉन्फ़िगर कर सकते हैं।

इसकी अपनी कमियां भी हैं, लेकिन यह आपके मामले में काम कर सकती है।


बाइंडिंग लोकलहोस्ट पोर्ट की अपनी कमियां हैं। नया डॉकटर नेटवर्किंग इसे पुराना बनाता है।
इवान अनिशचुक

0

विकल्प का उपयोग करने के लिए एक और विकल्प है --net container:$CONTAINER_ID

चरण 1: "नेटवर्क" कंटेनर बनाएं

docker run --name db_net ubuntu:14.04 sleep infinity
docker run --name app1_net --link db_net:db ubuntu:14.04 sleep infinity
docker run --name app2_net --link db_net:db ubuntu:14.04 sleep infinity
docker run -p 80 -p 443 --name nginx_net --link app1_net:app1 --link app2_net:app2 ubuntu:14.04 sleep infinity

चरण 2: "नेटवर्क" कंटेनरों में सेवाओं को इंजेक्ट करें

docker run --name db --net container:db_net pgsql
docker run --name app1 --net container:app1_net app1
docker run --name app2 --net container:app1_net app2
docker run --name nginx --net container:app1_net nginx

जब तक आप "नेटवर्क" कंटेनरों को नहीं छूते हैं, तब तक आपके लिंक के आईपी पते नहीं बदलने चाहिए।


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

0

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

यह कंटेनरों के बीच किसी भी प्रकार की निर्भरता को नहीं जोड़ता है - वे तब तक संवाद कर सकते हैं जब तक दोनों चल रहे हैं, फिर से शुरू और प्रतिस्थापन और लॉन्च ऑर्डर की परवाह किए बिना। यह DNS का आंतरिक रूप से उपयोग करता है, मेरा मानना ​​है कि / etc / मेजबान के बजाय

इसे इस तरह उपयोग करें: docker run --net=some_user_definied_nw --net-alias postgres ...और आप एक ही नेटवर्क पर किसी भी कंटेनर से उस उपनाम का उपयोग करके इसे कनेक्ट कर सकते हैं।

डिफ़ॉल्ट नेटवर्क पर काम नहीं करता है, दुर्भाग्य से, आपको एक के साथ एक बनाना होगा docker network create <network>और फिर इसे --net=<network>प्रत्येक कंटेनर के लिए उपयोग करना होगा ( यह अच्छी तरह से समर्थन करता है )।

कंटेनर के नीचे होने के कारण और इसलिए कई अन्य कंटेनरों द्वारा पहुंच से बाहर हो सकता है, इस मामले में यह भी गारंटी नहीं है कि यह सही नहीं है। लेकिन कुछ मामलों में जो सहज उन्नयन के साथ मदद कर सकता है, शायद।

यह सब बहुत अच्छी तरह से अभी तक प्रलेखित नहीं है, केवल मैन पेज को पढ़कर यह पता लगाना मुश्किल है।

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