Skip to main content
CI/CD8 min read

CI/CD में Docker Compose कनेक्शन त्रुटियों को ठीक करना

Jenkins में 'कनेक्शन अस्वीकृत' त्रुटियों को डीबग करने में 4 घंटे बिताए। CI पाइपलाइनों में Docker नेटवर्किंग के बारे में यहाँ मैंने क्या सीखा।

Part ofCloud & Infrastructure->
By Jason TeixeiraJanuary 5, 2024
DockerJenkinsCI/CDTroubleshooting
Share:
On this page

कल्पना करें: आपका Docker Compose सेटअप आपकी लोकल मशीन पर पूरी तरह काम करता है। आप CI में पुश करते हैं, और अचानक हर इंटीग्रेशन टेस्ट Connection refused के साथ फेल हो जाता है।

डेटाबेस कंटेनर "चल रहा" है। API कंटेनर "स्वस्थ" है। टेस्ट प्रक्रिया शुरू होती है। फिर वह आवश्यक सेवा से कनेक्ट नहीं हो पाती।

यह विफलता यादृच्छिक लगती है जब तक आपको एक बात याद न आए: लोकल Docker नेटवर्किंग और CI Docker नेटवर्किंग एक ही वातावरण नहीं हैं।

लोकल सेटअप आपको धोखा देता है

आपकी मशीन पर, आप Postgres से localhost:5432 पर कनेक्ट कर सकते हैं।

Compose नेटवर्क के अंदर, एक अन्य कंटेनर को आमतौर पर postgres:5432 से कनेक्ट करना चाहिए, जहाँ postgres सेवा का नाम है।

CI में, टेस्ट रनर हो सकता है:

  • Compose नेटवर्क के अंदर
  • होस्ट पर Compose नेटवर्क के बाहर
  • CI सर्विस कंटेनर के अंदर
  • नेस्टेड Docker एक्जीक्यूटर के अंदर

ये चार मामले अलग-अलग होस्टनेम का उपयोग करते हैं।

यही कारण है कि एक कनेक्शन स्ट्रिंग लोकल पर "सही" और पाइपलाइन में गलत हो सकती है।

पहले, पहचानें कि टेस्ट प्रक्रिया कहाँ चलती है

पोर्ट बदलने से पहले, एक प्रश्न पूछें:

क्या टेस्ट कमांड Compose सेवा के अंदर चल रहा है या CI होस्ट पर?

यदि टेस्ट Compose के अंदर चलते हैं:

code panelTXT
DATABASE_URL=postgres://user:pass@postgres:5432/app

यदि टेस्ट CI होस्ट पर चलते हैं और Compose ने पोर्ट प्रकाशित किया है:

code panelTXT
DATABASE_URL=postgres://user:pass@127.0.0.1:5432/app

यदि टेस्ट एक अलग CI कंटेनर में चलते हैं, तो CI प्लेटफ़ॉर्म की सर्विस नेटवर्किंग कॉन्फ़िगर होने तक कोई भी काम नहीं कर सकता है।

CI नेटवर्किंग निर्णयcompose -> tests
Compose सेवानेटवर्कटेस्ट रनरडेटाबेस

सही होस्टनेम इस बात पर निर्भर करता है कि टेस्ट रनर कहाँ रहता है। सेवा के नाम Compose नेटवर्क के अंदर काम करते हैं। प्रकाशित localhost पोर्ट होस्ट से काम करते हैं।

depends_on को तत्परता के रूप में न भरोसा करें

depends_on शुरुआती क्रम को नियंत्रित कर सकता है। यह गारंटी नहीं देता कि Postgres, Redis, या आपका ऐप कनेक्शन स्वीकार करने के लिए तैयार है।

सामान्य खराब संस्करण:

code panelYAML
services:
  api:
    depends_on:
      - postgres

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

हेल्थ चेक या एक स्पष्ट प्रतीक्षा स्क्रिप्ट का उपयोग करें।

code panelYAML
services:
  postgres:
    image: postgres:16
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app"]
      interval: 5s
      timeout: 5s
      retries: 12

  api:
    depends_on:
      postgres:
        condition: service_healthy

यह अभी भी हर CI प्लेटफ़ॉर्म को हल नहीं करता है, लेकिन यह सबसे आम रेस को हटा देता है।

चार विफलता वर्गों की जाँच करें

जब मैं Connection refused देखता हूँ, तो मैं इस क्रम में काम करता हूँ।

TCP जाँच उबाऊ लेकिन उपयोगी है:

code panelBASH
node -e "require('net').connect(5432, process.env.DB_HOST).on('connect', () => { console.log('ok'); process.exit(0) }).on('error', e => { console.error(e.message); process.exit(1) })"

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

विभिन्न सीमाओं के लिए अलग-अलग कनेक्शन स्ट्रिंग का उपयोग करें

एक साफ पैटर्न सीमा को स्पष्ट बनाना है:

code panelENV
DATABASE_URL_INTERNAL=postgres://app:app@postgres:5432/app
DATABASE_URL_HOST=postgres://app:app@127.0.0.1:5432/app

फिर आपका CI जॉब इस आधार पर सही चुनता है कि कमांड कहाँ चलता है।

यह एक URL को हर जगह काम करने की कोशिश करने से कम जादुई है।

माइग्रेशन को तत्परता से अलग रखें

एक डेटाबेस स्कीमा तैयार होने से पहले स्वस्थ हो सकता है।

यदि आपके ऐप को माइग्रेशन की आवश्यकता है, तो इसे एक स्पष्ट पाइपलाइन चरण बनाएँ:

code panelBASH
docker compose up -d postgres
docker compose run --rm migrate
docker compose run --rm test

या टेस्ट को एक सेवा के अंदर चलाएँ जो दोनों की प्रतीक्षा करती है:

  • डेटाबेस स्वास्थ्य
  • माइग्रेशन पूर्ण
  • सीड डेटा लोड

अन्यथा आपको एक बदतर प्रकार की विफलता मिलती है: रुक-रुक कर होने वाली टेस्ट त्रुटियाँ जो ऐप बग की तरह दिखती हैं लेकिन वास्तव में सेटअप रेस हैं।

डीबग आउटपुट जो मैं हर CI विफलता में चाहता हूँ

सीक्रेट डंप न करें। एनवायरनमेंट का आकार प्रिंट करें।

उपयोगी आउटपुट:

  • Docker Compose सेवाएँ और स्थिति
  • निर्भरता के लिए कंटेनर लॉग
  • पासवर्ड रिडैक्टेड के साथ रिज़ॉल्व किया गया होस्ट और पोर्ट
  • नेटवर्क नाम
  • हेल्थ-चेक स्थिति
  • माइग्रेशन स्थिति

उदाहरण:

code panelBASH
docker compose ps
docker compose logs --tail=80 postgres
docker network ls

लक्ष्य अगली विफलता को एक पास में निदान योग्य बनाना है।

प्रोडक्शन सबक

CI नेटवर्किंग दर्द प्रोडक्शन इंटीग्रेशन दर्द का एक पूर्वावलोकन है।

यदि आपके टेस्ट उम्मीद पर निर्भर हैं, तो आपकी डिप्लॉयमेंट शायद भी ऐसा ही करती हैं। सेवा सीमाओं को स्पष्ट बनाएँ। हेल्थ चेक जोड़ें। तत्परता को माइग्रेशन से अलग करें। सही तथ्यों को लॉग करें।

इस तरह आप "मेरी मशीन पर काम करता है" को किसी ऐसी चीज़ में बदल देते हैं जिसे पाइपलाइन साबित कर सकती है।

Reader route

article -> proof -> offer

ReadClusterProofScope

cluster

Cloud & Infrastructure

intent

CI/CD

route

next step

What to do with this

Turn the note into a build path.

If this topic maps to a real business problem, keep reading the cluster, study the academy path, or route the work into a scoped engagement.

Jason Teixeira
Written by
Jason Teixeira
Founder, Sage Ideas Studio · Principal Engineer
livebuild 5d6c8652026-08-05 06:00Z
// solo studio// no analytics resold// every commit human-reviewed