कई डॉकटर-कंपोज प्रोजेक्ट के बीच संचार


253

मेरे पास दो अलग-अलग docker-compose.ymlफ़ाइलों में दो अलग-अलग फ़ोल्डर हैं:

  • ~/front/docker-compose.yml
  • ~/api/docker-compose.yml

मैं यह कैसे सुनिश्चित कर सकता हूं कि एक कंटेनर एक कंटेनर में frontअनुरोध भेज सकता है api?

मुझे पता है कि एक व्यक्तिगत कंटेनर --default-gatewayका उपयोग करके विकल्प सेट किया जा सकता है docker run, ताकि इस कंटेनर को एक विशिष्ट आईपी पता सौंपा जा सके, लेकिन ऐसा लगता है कि उपयोग करते समय यह विकल्प उपलब्ध नहीं है docker-compose

वर्तमान में मैं एक काम कर रहा हूं docker inspect my_api_container_idऔर आउटपुट में गेटवे को देखता हूं । यह काम करता है लेकिन समस्या यह है कि यह आईपी बेतरतीब ढंग से जिम्मेदार है, इसलिए मैं इस पर भरोसा नहीं कर सकता।

इस प्रकार का एक और रूप इस प्रकार हो सकता है:

  • क्या मैं डॉकटर-कंपोज़ का उपयोग करके किसी विशेष कंटेनर के लिए एक निश्चित आईपी पते को निर्दिष्ट कर सकता हूं?

लेकिन अंत में मैं क्या देख रहा हूँ:

  • दो अलग-अलग डॉकटर-कंपोज़ प्रोजेक्ट एक दूसरे के साथ कैसे संवाद कर सकते हैं?

4
मैंने आज फिर इस पर गौर किया। देवताओं ने अंतत: नामकरण कर दिया है और मनमाने ढंग से नेटवर्क के नामकरण की अनुमति दी है। कम्पोज़ फ़ाइल संस्करण 3.5 का उपयोग करके आप 'नेटवर्क' कुंजी के तहत डिफ़ॉल्ट नेटवर्क के लिए एक नाम निर्दिष्ट कर सकते हैं। यह सामान्य प्रोजेक्ट नाम उपसर्ग के बिना एक नामित नेटवर्क बनाएगा यदि यह मौजूद नहीं है ..
cstrutton

जवाबों:


325

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

# front/docker-compose.yml
version: '2'
services:
  front:
    ...
    networks:
      - some-net
networks:
  some-net:
    driver: bridge

...

# api/docker-compose.yml
version: '2'
services:
  api:
    ...
    networks:
      - front_some-net
networks:
  front_some-net:
    external: true

नोट: आपके ऐप के नेटवर्क को "प्रोजेक्ट नाम" के आधार पर एक नाम दिया गया है, जो उस निर्देशिका के नाम पर आधारित है जिसमें वह रहता है, इस मामले में एक उपसर्ग front_जोड़ा गया था

वे तब सेवा नाम का उपयोग करके एक दूसरे से बात कर सकते हैं। से frontआप कर सकते हैं ping apiऔर इसके विपरीत।


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

3
रॉबर्ट मोस्कल केवल तभी जब आप अपने डॉकटर के आईपी को कंटेनरों में रखने के लिए चारों ओर हैक करते हैं। बेहतर है कि उन्हें एक सामान्य डॉक-परिभाषित नेटवर्क पर संवाद करना चाहिए।
जॉन्ह्र्र्र्र्र्र्र्स

2
कृपया ध्यान दें कि नेटवर्क के लिए "सामने_" उपसर्ग स्वचालित रूप से उसके चालू होने वाले फ़ोल्डर से बनाया जाता है। इसलिए यदि आपकी पहली docker- रचना फ़ाइल "उदाहरण / docker-compose.yml" में स्थित होगी, तो इसे "example_default" कहा जाएगा।
एंग्रीबंटूएनरड

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

2
@SteveB - ध्यान दें कि नाम संपत्ति केवल
docker

78

@ Johnharris85 के शानदार जवाब के लिए बस एक छोटा सा विज्ञापन, जब आप एक डॉक कम्पोज़ फ़ाइल चला रहे हैं, तो एक " default" नेटवर्क बनाया जाता है, ताकि आप इसे बाहरी नेटवर्क के रूप में दूसरी कंपोज़ फ़ाइल में जोड़ सकें:

# front/docker-compose.yml 
version: '2' 
  services:   
    front_service:
    ...

...

# api/docker-compose.yml
version: '2'
services:
  api_service:
    ...
    networks:
      - front_default
networks:
  front_default:
    external: true

मेरे लिए यह दृष्टिकोण अधिक अनुकूल था क्योंकि मेरे पास पहला डॉकटर-कंपोज फाइल नहीं था और इसके साथ संवाद करना चाहता था।


इस बाहरी नेटवर्क के लिए स्थिर आईपी आवंटित करने का सही तरीका है। मैंने इसे services:टैग के भीतर करने का आग्रह किया, तो सिंटैक्स को networks:नेस्टेड किया जाएगा front_default:("-" हटाएं) और फिर हम एक स्थिर आईपी को घोंसले में ipv4_address: '172.20.0.44'
डालते हैं

76

अद्यतन: लिखें फ़ाइल संस्करण 3.5 के रूप में:

अब यह काम करता है:

version: "3.5"
services:
  proxy:
    image: hello-world
    ports:
      - "80:80"
    networks:
      - proxynet

networks:
  proxynet:
    name: custom_network

docker-compose up -d'custom_network' नामक एक नेटवर्क से जुड़ जाएगा। यदि यह मौजूद नहीं है, तो इसे बनाया जाएगा!

root@ubuntu-s-1vcpu-1gb-tor1-01:~# docker-compose up -d
Creating network "custom_network" with the default driver
Creating root_proxy_1 ... done

अब, आप यह कर सकते हैं:

version: "2"
services:
  web:
    image: hello-world
    networks:
      - my-proxy-net
networks:
  my-proxy-net:
    external:
      name: custom_network

यह एक कंटेनर बनाएगा जो बाहरी नेटवर्क पर होगा।

मुझे अभी तक डॉक्स में कोई संदर्भ नहीं मिला लेकिन यह काम करता है!


क्या आपको एक विशिष्ट क्रम में दो सेवाओं को शुरू करना है? क्या आप एक को शुरू कर सकते हैं, और पहला एक नेटवर्क बनाएगा और दूसरा कौन इसमें शामिल होगा?
स्लैशडॉटिर

4
पहली सेवा (प्रॉक्सी ऊपर) नेटवर्क बनाती है। दूसरे उदाहरण में वाक्यविन्यास इसमें शामिल होता है।
cstrutton

2
@slashdottir आप नेटवर्क को दूसरी सेवा में बाहरी के रूप में चिह्नित नहीं कर सकते हैं और इसे तब बनाया जाएगा जब यह अभी तक मौजूद नहीं है।
बी

2
यह वास्तव में कारगर है। मैं बस नवीनतम docker रचना के साथ एक DO छोटी बूंद को काट दिया। मैंने उदाहरण को वास्तविक कामकाजी उदाहरण के लिए संपादित किया है।
क्रेस्टटन

1
मेरे मामले में, यह स्वीकृत उत्तर की तुलना में अधिक उपयुक्त समाधान निकला। बाहरी नेटवर्क के साथ समस्या यह थी कि पूर्वनिर्धारित क्रम में कंटेनरों को शुरू करना आवश्यक था। मेरे मुवक्किल के लिए, यह स्वीकार्य नहीं था। एक नामित नेटवर्क (3.5 के बाद से) सही समाधान निकला। धन्यवाद।
ygor

25

निम्नलिखित कन्टैंट से सभी कंटेनर डिफ़ॉल्ट नेटवर्क में apiशामिल हो सकते हैं :front

# api/docker-compose.yml

...

networks:
  default:
    external:
      name: front_default

डॉकटर कम्पोज़ गाइड देखें: पहले से मौजूद नेटवर्क का उपयोग करना (नीचे देखें)


12

पिछली पोस्ट की जानकारी सही है, लेकिन इसमें कंटेनरों को जोड़ने के तरीके के बारे में विवरण नहीं है, जिन्हें "external_links" के रूप में जोड़ा जाना चाहिए।

आशा है कि यह उदाहरण आपके लिए और अधिक स्पष्ट कर देगा:

  • मान लें कि आपके पास दो सेवाओं (svc11 और svc12) के साथ app1 / docker-compose.yml है, और app2 / docker-compose.yml को दो और सेवाओं (svc21 और svc22) के साथ मिलाएं और मान लें कि आपको एक पार किए गए फैशन में कनेक्ट करने की आवश्यकता है:

  • svc11 को svc22 के कंटेनर से कनेक्ट करने की आवश्यकता है

  • svc21 को svc11 के कंटेनर से कनेक्ट करने की आवश्यकता है।

तो कॉन्फ़िगरेशन इस तरह होना चाहिए:

यह app1 / docker-compose.yml है:


version: '2'
services:
    svc11:
        container_name: container11
        [..]
        networks:
            - default # this network
            - app2_default # external network
        external_links:
            - container22:container22
        [..]
    svc12:
       container_name: container12
       [..]

networks:
    default: # this network (app1)
        driver: bridge
    app2_default: # external network (app2)
        external: true

यह app2 / docker-compose.yml है:


version: '2'
services:
    svc21:
        container_name: container21
        [..]
        networks:
            - default # this network (app2)
            - app1_default # external network (app1)
        external_links:
            - container11:container11
        [..]
    svc22:
       container_name: container22
       [..]

networks:
    default: # this network (app2)
        driver: bridge
    app1_default: # external network (app1)
        external: true

6

कंपोज़ 1.18 (स्पेक 3.5) के बाद से, आप अपनी ज़रूरत के सभी कंपोज़ YAML फ़ाइलों के लिए अपने स्वयं के कस्टम नाम का उपयोग करके डिफ़ॉल्ट नेटवर्क को ओवरराइड कर सकते हैं। यह निम्नलिखित के रूप में सरल है:

networks:
  default:
    name: my-app

ऊपर आप है मान लिया गया है versionकरने के लिए सेट 3.5(ऊपर अगर वे 4 में यह विरोध नहीं है या)।

अन्य उत्तरों ने भी यही बताया है; यह एक सरलीकृत सारांश है।


2

मैं सुनिश्चित करूंगा कि सभी कंटेनर docker-composeएक ही समय में एक ही समय में एक साथ उपयोग करके एक ही नेटवर्क के लिए घ हैं :

docker compose --file ~/front/docker-compose.yml --file ~/api/docker-compose.yml up -d

उदाहरण के लिए, मुझे एक कंटेनर के सामने के एक कंटेनर से linkया बनाने के लिए अनुमति देगा depends_on?
जीवन

वास्तव में जब मैं आपको सुझाव देता हूं, तो डॉकटर-कंपोज़ build path ~/front/api either does not exist or is not accessibleया तो या दूसरे तरीके से उत्तर देते हैं ,build path ~/api/front either does not exist or is not accessible
जीवन

1
यदि आप उन्हें उसी समय बना रहे हैं तो आपको इसकी आवश्यकता नहीं होनी चाहिए। एक नेटवर्क पर अपने सभी कंटेनर के साथ बनाया जाएगा, वे सब लिखें फ़ाइल (से सेवा का नाम माध्यम से संवाद करने में सक्षम हो जाएगा नहीं कंटेनर नाम)।
नौरौषन

यह आसान हो सकता है यदि दो कंपोज़ फाइलें एक ही फ़ोल्डर में हों। लेकिन मुझे नहीं लगता कि यह आवश्यक है - मुझे लगता है कि इसे किसी भी तरह से काम करना चाहिए।
नौरौषन

2
यह समाधान काम नहीं करता है, इस धागे पर मेरी टिप्पणी देखें: github.com/docker/compose/issues/3530#issuecomment-22242490501
johnharris85

2

अद्यतन: लिखें फ़ाइल संस्करण 3.5 के रूप में:

मैं इसी तरह की समस्या के साथ आया था और मैंने अपने डॉकटर-कम्पोज़.आईएमएल प्रोजेक्ट में एक छोटे से बदलाव को जोड़कर इसे हल किया।

उदाहरण के लिए हम दो एपीआई है scoringऔर nerScoringएपीआई nerको इनपुट अनुरोध को संसाधित करने के लिए एपीआई को अनुरोध भेजने की आवश्यकता है । आदेश में कि वे दोनों एक ही नेटवर्क को साझा करने के लिए मान रहे हैं।

नोट: हर कंटेनर का अपना नेटवर्क होता है जो ऐप को डॉकटर के अंदर चलाने के समय अपने आप बन जाता है। उदाहरण के लिए ner api नेटवर्क को बनाया जाएगा ner_defaultऔर स्कोरिंग api नेटवर्क को नाम दिया जाएगा scoring default। यह समाधान संस्करण के लिए काम करेगा: '3'।

जैसा कि ऊपर के परिदृश्य में मेरी स्कोरिंग एपी नीर आपी के साथ संवाद करना चाहती है तो मैं निम्नलिखित पंक्तियों को जोड़ दूंगा। जिसका मतलब है कि जब भी मैं ner api के लिए कंटेनर बनाता हूं तो यह स्वतः ही स्कोरिंग_डेफ़ॉल्ट नेटवर्क में जुड़ जाता है।

networks:
  default:
      external:
        name: scoring_default

नेर / डोकर-compose.yml

version: '3'
services:
  ner:
    build: .
    ...

networks:
  default:
      external:
        name: scoring_default

स्कोरिंग / डोकर-compose.yml

version: '3'
services:
  api:
    build: .
    ...

हम यह देख सकते हैं कि कैसे उपरोक्त कंटेनर अब उसी नेटवर्क का हिस्सा हैं जिसे scoring_defaultकमांड का उपयोग किया जाता है :

docker scoring_default का निरीक्षण करते हैं

{
    "Name": "scoring_default",
        ....
    "Containers": {
    "14a6...28bf": {
        "Name": "ner_api",
        "EndpointID": "83b7...d6291",
        "MacAddress": "0....",
        "IPv4Address": "0.0....",
        "IPv6Address": ""
    },
    "7b32...90d1": {
        "Name": "scoring_api",
        "EndpointID": "311...280d",
        "MacAddress": "0.....3",
        "IPv4Address": "1...0",
        "IPv6Address": ""
    },
    ...
}

1

आप .envअपनी सभी परियोजनाओं में एक फ़ाइल जोड़ सकते हैं COMPOSE_PROJECT_NAME=somename

COMPOSE_PROJECT_NAME ने संसाधनों को नाम देने के लिए उपयोग किए गए उपसर्ग को ओवरराइड किया, क्योंकि आपकी सभी परियोजनाएं somename_defaultउनके नेटवर्क के रूप में उपयोग करेंगी , जिससे सेवाओं के लिए एक-दूसरे के साथ संवाद करना संभव होगा क्योंकि वे एक ही परियोजना में थे।

नायब: आपको अन्य परियोजनाओं से निर्मित "अनाथ" कंटेनरों के लिए चेतावनी मिलेगी।


0
version: '2'
services:
  bot:
    build: .
    volumes:
      - '.:/home/node'
      - /home/node/node_modules
    networks:
      - my-rede
    mem_limit: 100m
    memswap_limit: 100m
    cpu_quota: 25000
    container_name: 236948199393329152_585042339404185600_bot
    command: node index.js
    environment:
      NODE_ENV: production
networks:
  my-rede:
    external:
      name: name_rede_externa

0

एक और डॉक-कंपोज़ नेटवर्क का उपयोग करने के लिए आप बस ये करें (डॉकटर-कंपोज़ के बीच नेटवर्क साझा करने के लिए):

  1. द्वारा पहला डॉकटर-कंपोज़ प्रोजेक्ट चलाएँ up -d
  2. पहले डॉकटर-कंपोज़ के नेटवर्क नाम को खोजें: docker network ls(इसमें रूट डायरेक्टरी प्रोजेक्ट का नाम शामिल है)
  3. फिर दूसरे डॉकटर-कम्पोज़ फ़ाइल में नीचे इस संरचना द्वारा उस नाम का उपयोग करें।

दूसरा डॉकटर-कंपोज

version: '3'
services:
  service-on-second-compose:  # Define any names that you want.
    .
    .
    .
    networks:
      - <put it here(the network name that comes from "docker network ls")>

networks:
  - <put it here(the network name that comes from "docker network ls")>:
    external: true

0

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

उदाहरण app1 - सेवा लाइनों में बनाया गया नया-नेटवर्क, बाहरी के रूप में चिह्नित करें: नीचे दिए गए app2 पर सही - ऊपर जाने पर app1 द्वारा बनाया गया "नया-नेटवर्क" इंगित करें, बाहरी रूप में चिह्नित करें: तल पर सही, और कॉन्फ़िगरेशन में सेट करें कनेक्ट करने के लिए, इस नेट में app1 कि आईपी।

इसके साथ, आपको एक दूसरे के साथ बात करने में सक्षम होना चाहिए

* यह तरीका सिर्फ स्थानीय-परीक्षण पर ध्यान केंद्रित करने के लिए है, ताकि जटिल कॉन्फ़िगरेशन पर काम न किया जा सके ** मुझे पता है कि यह बहुत 'पैच तरीका' है, लेकिन मेरे लिए काम करता है और मुझे लगता है कि कुछ अन्य लोग इसका लाभ उठा सकते हैं


0

अगर आप

  • विभिन्न डॉकटर-कंपोज़ प्रोजेक्ट से दो कंटेनरों के बीच संवाद करने की कोशिश कर रहा है और एक ही नेटवर्क का उपयोग नहीं करना चाहता (क्योंकि मान लें कि उनके पास एक ही पोर्ट पर PostgreSQL या Redis कंटेनर होगा और आप इन पोर्ट को नहीं बदलना चाहेंगे और इसका उपयोग नहीं करना चाहेंगे उसी नेटवर्क पर)
  • स्थानीय रूप से विकसित करना और दो डॉकटर रचनाओं के बीच संचार की नकल करना चाहते हैं
  • लोकलहोस्ट पर दो डॉक-कंपोज़ प्रोजेक्ट चला रहा है
  • विशेष रूप से Django एप्लिकेशन या Django रेस्ट फ्रेमवर्क (drf) एपीआई और कुछ एक्सपोज्ड पोर्ट पर कंटेनर के अंदर चल रहे ऐप को विकसित करना
  • हो रही Connection refusedदो कंटेनरों के बीच संवाद की कोशिश करते हुए

और आप करना चाहते हैं

  • कंटेनर "समान नेटवर्क" के बिना (या इसके विपरीत) api_aसंवाद करता हैapi_b

(नीचे उदाहरण)

आप दूसरे कंटेनर के "होस्ट" का उपयोग अपने कंप्यूटर और पोर्ट के आईपी के रूप में कर सकते हैं जो डॉकर कंटेनर के अंदर से मैप किया गया है। आप इस स्क्रिप्ट के साथ अपने कंप्यूटर का आईपी प्राप्त कर सकते हैं ( पायथन के स्टडीलिब का उपयोग करके स्थानीय आईपी पते ढूँढना ):

import socket
def get_ip():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        # doesn't even have to be reachable
        s.connect(('10.255.255.255', 1))
        IP = s.getsockname()[0]
    except:
        IP = '127.0.0.1'
    finally:
        s.close()
    return IP

उदाहरण:

project_api_a/docker-compose.yml:

networks:
  app-tier:
    driver: bridge

services:
  api:
    container_name: api_a
    image: api_a:latest
    depends_on:
      - postgresql
    networks:
      - app-tier

api_aकंटेनर के अंदर आप Django ऐप चला रहे हैं: manage.py runserver 0.0.0.0:8000

और दूसरा docker-compose.yml अन्य प्रोजेक्ट से:

project_api_b/docker-compose-yml :

networks:
  app-tier:
    driver: bridge

services:
  api:
    container_name: api_b
    image: api_b:latest
    depends_on:
      - postgresql
    networks:
      - app-tier

api_bकंटेनर के अंदर आप Django ऐप चला रहे हैं: manage.py runserver 0.0.0.0:8001

और कंटेनर से कनेक्ट करने का प्रयास तब कंटेनर api_aके api_bURL api_bहोगा: http://<get_ip_from_script_above>:8001/

यह विशेष रूप से मूल्यवान हो सकता है यदि आप दो से अधिक (तीन या अधिक) डॉक-कंपोज़ प्रोजेक्ट का उपयोग कर रहे हैं और यह सभी के लिए सामान्य नेटवर्क प्रदान करना कठिन है - यह अच्छा वर्कअराउंड और समाधान है

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