Docker नेटवर्क और पोर्ट फ़ॉरवर्डिंग
कंटेनर एक-दूसरे को कैसे देखते हैं, पोर्ट पब्लिश करना साधारण EXPOSE से कैसे अलग है, और Docker ufw के नियम क्यों बायपास कर देता है।
23 अगस्त 2026 को अपडेट किया गया
कंटेनर की आधी समस्याएँ नेटवर्क से जुड़ी होती हैं: कोई सर्विस डेटाबेस तक नहीं पहुँच पाती, कोई पोर्ट पहले से लिया हुआ है, और पैनल अचानक पूरे इंटरनेट पर खुल जाता है। आइए समझें कि यह सब कैसे काम करता है।
तीन तरह के नेटवर्क
- bridge — डिफ़ॉल्ट। कंटेनर को अंदरूनी एड्रेस मिलते हैं और वे आपस में बात करते हैं; बाहर की दुनिया में वे होस्ट के NAT से जाते हैं।
- host — कंटेनर सीधे होस्ट का नेटवर्क इस्तेमाल करता है; पोर्ट पब्लिश करना न ज़रूरी है, न काम करता है। तेज़ है, लेकिन कोई आइसोलेशन नहीं: कंटेनर का पोर्ट 80 यानी होस्ट का पोर्ट 80।
- none — कोई नेटवर्क ही नहीं। उन कामों के लिए जिन्हें नेटवर्क की ज़रूरत नहीं।
आपके या Compose के बनाए कस्टम नेटवर्क में डिफ़ॉल्ट bridge से एक अहम फ़र्क़ है: उसमें नाम से रिज़ॉल्यूशन काम करता है। app कंटेनर db नाम से db कंटेनर तक पहुँच सकता है।
docker network create backend
docker network ls
docker network inspect backend
Compose में ऐसा नेटवर्क हर प्रोजेक्ट के लिए अपने आप बन जाता है।
पोर्ट पब्लिश करना
ports:
- "127.0.0.1:8080:8080" # accessible only from the machine itself
- "80:80" # accessible to the whole internet
बाईं ओर होस्ट का पोर्ट है, दाईं ओर कंटेनर के अंदर का पोर्ट। इमेज में EXPOSE डायरेक्टिव कुछ पब्लिश नहीं करता: यह सिर्फ़ एक नोट है कि एप्लिकेशन किस पोर्ट पर सुनता है।
नियम आसान है: सिर्फ़ वही पब्लिश करें जो बाहर से पहुँचने योग्य होना चाहिए। डेटाबेस, पैनल और अंदरूनी API को 127.0.0.1 पर रखें, और सर्टिफ़िकेट वाला वेब सर्वर उन्हें बाहर के लिए खोलता है।
Docker
iptablesके नियम खुद लिखता है और यह कामufwके मैनेज किए चेन से पहले करता है।-p 8080:8080से पब्लिश किया पोर्ट इंटरनेट से पहुँचने योग्य रहेगा, भले हीufw“deny” दिखाए। फ़ायरवॉल पर भरोसा न करें — पोर्ट को127.0.0.1से बाइंड करें।
कंटेनरों के बीच बातचीत
services:
app:
networks: [frontend, backend]
db:
networks: [backend]
proxy:
networks: [frontend]
ports:
- "80:80"
- "443:443"
networks:
frontend:
backend:
यहाँ डेटाबेस सिर्फ़ एप्लिकेशन के लिए पहुँचने योग्य है, और बाहर की ओर सिर्फ़ वेब सर्वर खुला है। किसी भी स्टैक के लिए यही सही सेटअप है।
कंटेनर के अंदर पड़ोसी को उसके सर्विस नाम से पुकारें: postgres://db:5432/app। कंटेनर के अंदर localhost का मतलब खुद कंटेनर होता है, होस्ट नहीं — यह latest के बाद दूसरी सबसे आम गलती है।
होस्ट पर ही चल रही किसी सर्विस तक कंटेनर से पहुँचने के लिए host.docker.internal नाम इस्तेमाल करें और यह जोड़ें:
extra_hosts:
- "host.docker.internal:host-gateway"
डायग्नोस्टिक्स
docker compose exec app ping -c2 db
docker compose exec app getent hosts db
sudo ss -tulpn | grep LISTEN
docker port <container>
ss दिखाएगा कि पोर्ट असल में किस इंटरफ़ेस पर सुन रहा है: 0.0.0.0:8080 — बाहर के लिए खुला, 127.0.0.1:8080 — नहीं।
आम गलतियाँ
- “Port already in use”। इसे कोई दूसरा कंटेनर या होस्ट की कोई सर्विस रोके हुए है।
sudo ss -tulpn | grep :80दोषी ढूँढ देगा। - अलग-अलग Compose प्रोजेक्ट के कंटेनर एक-दूसरे को नहीं देख पाते। हर प्रोजेक्ट का अपना नेटवर्क होता है। उन्हें
networks: { shared: { external: true } }से साफ़-साफ़ जोड़ें। - एप्लिकेशन कंटेनर के अंदर
127.0.0.1पर सुन रहा है। तब पब्लिश करने से फ़ायदा नहीं होगा: कंटेनर के बाहर से उस तक पहुँचा ही नहीं जा सकता। एप्लिकेशन को0.0.0.0पर सुनने के लिए कॉन्फ़िगर करें। - बैंडविड्थ। हर होस्ट पर 500 Mbps तक साझा। फ़ाइल डिस्ट्रीब्यूशन इसे बाकी सबके साथ बाँटता है।