کنٹینر VPN-فقط API تک نہیں پہنچ رہا؟ اسے میزبان پر پراکسی کریں
ٹنل میزبان پر رہتا ہے، اس لیے کنٹینر کے پاس نجی پتے تک کوئی راستہ نہیں۔ ایک تنگ ریورس پراکسی شائع کریں اور اسے host.docker.internal کے نام سے پکارا کریں۔
آپ کی Compose سروس اُس API کے سامنے وقت سے گزر جاتی ہے جسے اسی مشین کا براؤزر بغیر کسی شکایت کے کھولتا ہے۔ یہی فرق سراغ ہے: کام کرنے والی درخواست VPN ٹنل والے میزبان سے نکلتی ہے، اور لٹک جانے والی درخواست اپنا نیٹ ورک اسٹیک رکھنے والے کنٹینر سے۔ کنٹینر کے اندر کوئی چیز ٹنل کے راستے نہیں جانتی، اس لیے نام کیسے بھی لکھا جائے نجی منزل ناقابلِ رسائی رہتی ہے۔ حل میزبان کے ذریعے جان بوجھ کر کی گئی چھلانگ ہے، زیادہ چالاک روٹ ٹیبل نہیں۔
دو راستے کیوں مختلف ہیں اس سے شروع کریں، پھر طے کریں کہ ٹنل کہاں رہنی چاہیے۔
میزبان کیوں کام کرتا ہے اور کنٹینر کیوں نہیں
ٹنل اٹھانے سے میزبان کو ایک انٹرفیس، راستوں کا مجموعہ اور عام طور پر VPN کا فراہم کردہ resolver اندراج ملتا ہے۔ کنٹینر کو اس میں سے کچھ بھی وراثت میں نہیں ملتا: وہ انجن کے پل پر ایک انٹرفیس اور اسی پل کی طرف اشارہ کرنے والے ڈیفالٹ راستے کے ساتھ شروع ہوتا ہے۔ میزبان پر نصب راستے اُس نام کی جگہ کے اندر چلنے والی کسی چیز کو نظر نہیں آتے۔
اسی لیے علامات صرف خراب نہیں بلکہ متضاد دکھائی دیتی ہیں۔ میزبان نجی نام حل کر کے جڑ جاتا ہے، کیونکہ وہاں نام اور راستہ دونوں موجود ہیں۔ کنٹینر اپنا پیکٹ ایسے نجی پتے پر بھیجتا ہے جہاں پل کے راستے پر کوئی چیز نہیں پہنچ سکتی، اور درخواست وقت سے گزر جاتی ہے۔ کنٹینر کی hosts فائل میں نام شامل کرنے سے کچھ نہیں بدلتا، کیونکہ پتہ بذاتِ خود وہاں سے ناقابلِ رسائی ہے جہاں کنٹینر بیٹھا ہے۔
کنٹینر کے اندر سے میزبان تک پہنچیں
کنٹینر میں عمل جو localhost ڈائل کرتا ہے وہ کنٹینر کو ڈائل کر رہا ہے۔ Docker Desktop host.docker.internal کو ایسے نام کے طور پر شائع کرتا ہے جو انجن چلانے والی مشین کی طرف واپس اشارہ کرتا ہے؛ Linux انجن اسے غیر متعین رکھتے ہیں جب تک سروس نہ مانگے، اور نیچے دیا گیا میپنگ یہی کرتا ہے۔ اس سے ایپلیکیشن نجی پتے کے بجائے نام اور پورٹ کو ہدف بناتی ہے۔
services:
app:
extra_hosts:
- "host.docker.internal:host-gateway"
environment:
INTERNAL_API_HOST: "host.docker.internal:8666"ٹنل چھلانگ کے میزبان جانب ہی رہتی ہے، اور اُس متغیر میں پورٹ وہی ہے جس پر پراکسی سنے گی۔ ٹنل کھو دینے والا کنٹینر اب کبھی نہ ہونے والے راستے کی کوشش کے بجائے ایک معلوم چھلانگ پر ناکام ہوتا ہے۔
منتخب کریں کہ ٹنل کہاں رہتی ہے
نجی API کی ضرورت والی Compose سروس کے لیے تین شکلیں ممکن ہیں، اور وہ اس میں مختلف ہیں کہ کون سا عمل ٹنل کا مالک ہے۔ VPN کلائنٹ کنٹینر امیج کے اندر چل سکتا ہے، جس کے لیے ٹنل ڈیوائس کھولنا اور اس کے ساتھ آنے والی نیٹ ورک انتظامی صلاحیت دینا ضروری ہے۔ ایپلیکیشن الگ ٹنل کنٹینر کا نیٹ ورک نام کی جگہ شیئر کر سکتی ہے، تاکہ دونوں عمل ایک اسٹیک اور ایک روٹ ٹیبل دیکھیں۔ یا ٹنل میزبان پر ہی رہ سکتی ہے، میزبان سے کنٹینر میں ایک تنگ فارورڈر کے ساتھ۔
پہلی دو پروفائل فائلیں، دوبارہ جڑنے کا رویہ اور resolver پالیسی منصوبے میں کھینچ لاتی ہیں، اور فائل کی ہر سروس کو ٹنل کی صحت پر منحصر بنا دیتی ہیں۔ ایک API کال کے لیے یہ بہت زیادہ بندھن ہے۔ ایک ہی داخلی اینڈ پوائنٹ پڑھنے والے ڈویلپمنٹ اسٹیک کے لیے میزبان جانب کا فارورڈر سب سے چھوٹی تبدیلی ہے جو اسناد وہیں رکھتا ہے جہاں پلیٹ فارم ٹیم انہیں سنبھالتی ہے۔
میزبان پر ایک تنگ راستہ شائع کریں
فارورڈر کو جو ورثے میں ملتا ہے اس سے شروع کریں: اسے ٹنل کا مالک اکاؤنٹ استعمال میں لے کر چلائیں، پھر اس کے باہر جانے والے ساکٹ میزبان کے راستے اور میزبان کا resolver لے لیں گے۔ nginx کا ایک location بلاک ایک راستہ ڈھکتا ہے۔
server {
listen 8666;
location /search/ {
proxy_pass http://10.20.30.40:8090/;
proxy_set_header Host internal-api.example;
proxy_read_timeout 60s;
}
}پتے اور پورٹ کو عارضی سمجھیں اور وہ جوڑی رکھیں جس پر API واقعی سنتا ہے۔ ہر اضافی upstream اپنے location بلاک کا حقدار ہے، اور ہر بلاک کو صرف وہی راستے قبول کرنے چاہئیں جو یہ سروس پکارتی ہے، تاکہ پراکسی نجی نیٹ ورک کا عام دروازہ نہ بن جائے۔ host-gateway سے آنے والے کلائنٹس کے لیے سننے والے کو پل کے پتے سے، اور loopback سے صرف اُس وقت باندھیں جب کلائنٹ میزبان کی نیٹ ورک نام کی جگہ شیئر کرے، اور کبھی 0.0.0.0 سے نہ باندھیں۔ ایسا پورٹ بھی منتخب کریں جو ابھی خالی ہو: پہلے سے لیا گیا نمبر پراکسی کو سننے سے روک دیتا ہے جبکہ کنٹینر وقت سے گزرتا رہتا ہے، جسے اُس نیٹ ورک خرابی سے الگ نہیں پہچانا جا سکتا جس سے آپ نے آغاز کیا تھا۔
پورٹس، نام اور TLS کا فیصلہ
ناموں کا حل راستہ بندی کی طرح بٹتا ہے۔ کنٹینر کی عوامی تلاشیں انجن کے resolver سے گزرتی ہیں، اس لیے میزبان پر حل ہونے والا نجی نام کنٹینر کے اندر حل نہیں ہوگا۔ پراکسی وہ جزو ہے جو نجی نام حل کرتا ہے، کیونکہ اسے میزبان کا resolver ورثے میں ملتا ہے۔
TLS وہ فیصلہ ہے جو مؤخر کیا جاتا ہے اور پھر اگلی ناکامی کی وضاحت کرتا ہے۔ اگر پراکسی بائٹس اچھوتے بھیجے، تو کنٹینر API کا اپنا سرٹیفکیٹ دیکھتا ہے اور اپنے اعتماد کے ذخیرے میں داخلی CA درکار ہوتا ہے۔ اگر پراکسی TLS ختم کرے، تو وہ اعتماد میزبان پر منتقل ہو جاتا ہے اور ایپلیکیشن موصول host ہیڈر سے روابط بنانے لگتی ہے۔ ایک ہی ترتیب منتخب کریں اور اسے ہر وسیلے پر لاگو کریں، کیونکہ دوسری کی جاری کردہ ری ڈائریکٹ ایسے میزبان نام کی طرف اشارہ کرتی ہے جسے کنٹینر حل نہیں کر سکتا۔
سروس کے اندر سے تصدیق کریں
درخواست میزبان سے نہیں، کنٹینر سے بھیجیں: پراکسی راستے پر سادہ curl، پھر ایپلیکیشن کی اپنی صحت کی جانچ۔ جب پراکسی جواب دے مگر ایپلیکیشن پھر بھی ناکام ہو، تو تین چیزیں موازنہ کریں: وہ بنیادی URL جو وہ بناتی ہے، اس کے ماحول میں کوئی بھی پراکسی متغیر، اور وہ CA جس پر بھروسا کرتی ہے۔ سب کنٹینر کے ماحول اور لاگز میں ہیں، اور ان میں سے کوئی ایک درست کرنے سے VPN پر اثر نہیں پڑتا۔
منتخب ترتیب کو تازہ رہتے ہوئے منصوبے کے README میں لکھیں۔ ورنہ اس وقت کی حد سے ٹکرانے والا اگلا شخص وہی دوپہر یہ دوبارہ دریافت کرنے میں گزارے گا کہ ٹنل میزبان پر رہتی ہے۔