ডেভ কন্টেইনার VPN-শুধু হোস্টে পৌঁছায় না: কোথায় দেখবেন
ব্রাউজার ও কন্টেইনারের রিজলভার, প্রক্সি ও রুটের প্রেক্ষাপট আলাদা। যেকোনো VPN সেটিং বদলানোর আগে ব্যর্থ প্রসেসটি কোনটি ব্যবহার করছে তা খুঁজে বের করুন।
ব্যক্তিগত API আপনার ডেস্কটপ ব্রাউজারে খোলে, কিন্তু ডেভেলপমেন্ট কন্টেইনারে ব্যর্থ হয়। এটি কোনো বিরোধ নয়, আর খুব কম ক্ষেত্রেই এর কারণ VPN নিজে। ব্রাউজারের অনুরোধ আর ব্যর্থ অনুরোধ দুটি ভিন্ন প্রসেস তৈরি করেছে, ভিন্ন রিজলভার, প্রক্সি ও রুট নিয়ে, এবং প্রায়ই সম্পূর্ণ ভিন্ন নেটওয়ার্ক নেমস্পেস থেকে। “আমার ল্যাপটপে” বলতে Windows হোস্ট, একটি WSL ডিস্ট্রিবিউশন, Docker Desktop ভার্চুয়াল মেশিন এবং সেই VM-এর ভেতরের একটি কন্টেইনার—এই চারটি প্রেক্ষাপট বোঝাতে পারে, যার প্রত্যেকটি একই হোস্টনামে ভিন্ন উত্তর দিতে পারে। একটি সেটিংও ছোঁয়ার আগে ব্যর্থ প্রসেসটি কোনটি ব্যবহার করছে তা জেনে নিন।
সেটিং বদলানোর আগে প্রসেসটি খুঁজুন
VPN ক্লায়েন্ট নয়, কন্টেইনার ইঞ্জিন দিয়ে শুরু করুন। কমান্ড লাইন কোন প্রেক্ষাপটের সঙ্গে কথা বলছে এবং সেই ইঞ্জিন কোন অপারেটিং সিস্টেমে চলছে তা জিজ্ঞাসা করুন, কারণ ডেস্কটপ VM দ্বারা পরিচালিত Linux কন্টেইনার স্থানীয় ডেমন দ্বারা পরিচালিত কন্টেইনারের চেয়ে ভিন্ন পথ নেয়:
docker context ls
docker info --format '{{.OperatingSystem}} / {{.Name}}'
docker run --rm alpine ip route
Windows-এ wsl -l -v বলে দেয় ডিস্ট্রিবিউশনটি WSL 2-এর অধীনে চলছে কি না, যা এটিকে নিজস্ব ভার্চুয়াল সুইচের পেছনে রাখে। এই খুঁটিনাটিই নির্ধারণ করে কন্টেইনারটি হোস্টের রাউটিং টেবিল ভাগ করে নেয়, নাকি এমন NAT-এর পেছনে বসে যার হোস্টে পৌঁছাতে ফরওয়ার্ড করা পোর্ট বা হোস্টনাম দরকার।
একটি অনুরোধ স্থির রাখুন এবং তুলনা করুন
ব্যক্তিগত হোস্টে একটি নিরীহ এন্ডপয়েন্ট বেছে নিন এবং প্রতিটি তুলনায় সেটিই ব্যবহার করুন: ব্রাউজার থেকে, হোস্ট টার্মিনাল থেকে, WSL ডিস্ট্রিবিউশন থেকে এবং কন্টেইনারের ভেতর থেকে। প্রতিটি প্রচেষ্টায় চারটি জিনিস লিখে রাখুন: রিজলভ হওয়া ঠিকানা, প্রক্সি ব্যবহৃত হয়েছে কি না, ব্যর্থতার শ্রেণি এবং অতিবাহিত সময়। নাম খোঁজা, সংযোগ স্থাপন, TLS যাচাই এবং HTTP স্ট্যাটাস—এগুলি চারটি আলাদা সমস্যা, আর এদের মিশিয়ে “কাজ করছে না” বানালে একটি সকাল নষ্ট হয়।
ব্যর্থ কন্টেইনারের ভেতরেই তুলনাটি চালান, টাইমআউট দিয়ে, যাতে নীরব ফায়ারওয়াল টার্মিনালটি মিনিটের পর মিনিট আটকে না রাখে। নতুন কন্টেইনার ইঞ্জিনের নেটওয়ার্ক প্রেক্ষাপট পুনরুৎপাদন করে, কিন্তু অ্যাপ্লিকেশন কন্টেইনারের নেমস্পেস, প্রক্সি ভেরিয়েবল বা রিজলভার নয়, তাই আসল কন্টেইনারে docker exec করাই নির্ভরযোগ্য পরীক্ষা, আর সাইডকার কেবল পার্থক্যটি ইঞ্জিনে না কন্টেইনারে তা আলাদা করার উপায়:
docker exec -it app /bin/sh -c "getent hosts api.internal; curl -v --max-time 8 https://api.internal/ 2>&1 | tail -20"
docker run --rm --network container:app curlimages/curl:latest -sv --max-time 8 https://api.internal/ 2>&1 | tail -20
alpine বেস ইমেজে busybox আছে, curl নেই, আর ঠিক এই ধরনের খুঁটিনাটিই কপি করা ডায়াগনস্টিক ব্লককে ব্যর্থ করে: ক্লায়েন্টসহ ইমেজ বেছে নিন, বা একই রানে সেটি যোগ করুন। সম্পর্কহীন পাবলিক সাইটের সঙ্গে তুলনা কিছুই আলাদা করে না। কন্টেইনার থেকে https://example.com কাজ করলে আপনি শুধু জেনেছেন কন্টেইনারের ইন্টারনেট অ্যাক্সেস আছে, টানেল দিয়ে ব্যক্তিগত ঠিকানায় পৌঁছায় কি না তা নয়। একইভাবে, নতুন টার্মিনাল খোলা কেবল প্রমাণ করে নতুন টার্মিনালটি কাজ করে, ব্যর্থ অ্যাপ্লিকেশনের সঙ্গে একই রানটাইম ভাগ করে তা নয়।
Docker Desktop VPN-এর সঙ্গে কাজ করতে পারে
Docker-এর নিজস্ব VPN ও হোস্ট সংযোগ বিষয়ক ডকুমেন্টেশন এটিকে সমর্থিত সেটআপ হিসেবে বর্ণনা করে, আর সৎ সারাংশ হল এটি কাজ করে, স্বয়ংক্রিয়ভাবে ভাঙা নয়। ধরে নেবেন না যে ডেস্কটপ VM ডিজাইনগতভাবেই হোস্ট টানেল এড়িয়ে যায়; অনেক সেটআপে ট্রাফিক সঠিকভাবে হোস্টের টানেল অনুসরণ করে, আর তাই “Docker VPN উপেক্ষা করে” কিংবদন্তি আত্মবিশ্বাসী ও ভুল পরামর্শ তৈরি করে।
যা এখনও গুরুত্বপূর্ণ তা হল ব্যবহৃত backend, ক্লায়েন্টের স্প্লিট-টানেল নীতি এবং VM যে রিজলভার কনফিগারেশন পেয়েছে। যে VPN ক্লায়েন্ট রুট ইনস্টল করে কিন্তু DNS নয়, বা এমন DNS সার্ভার পুশ করে যা VM-এর নাগালের বাইরে, সে কন্টেইনারের ভেতরে নাম খোঁজার ব্যর্থতা তৈরি করে, অথচ হোস্ট কাজ করে কারণ হোস্টের অতিরিক্ত রিজলভার বা ক্যাশ করা উত্তর আছে। এটি কন্টেইনারের পোশাক পরা রিজলভার সমস্যা। আপনি যতবার VPN পুনঃসংযোগ করেন এটি ততবার টিকে থাকে, কারণ টানেল ইতিমধ্যেই সেই ট্রাফিক বহন করছে যা বহন করতে আপনি বলেছিলেন।
ঠিকানা ওভারল্যাপ ও MTU আলাদা ব্যর্থতা
দুটি ব্যর্থতা আলাদা রোগনির্ণয় দাবি করে, কারণ এগুলিকে প্রায়ই অ্যাক্সেস নীতি ভাবা হয়। প্রথমটি ঠিকানা ওভারল্যাপ: VPN যদি এমন রেঞ্জ পুশ করে যা কন্টেইনার নেটওয়ার্কের ডিফল্ট ব্রিজ সাবনেটের সঙ্গে সংঘর্ষ করে, তবে সেই রেঞ্জের জন্য কন্টেইনারের রুট স্থানীয় ব্রিজের দিকে নির্দেশ করে এবং কখনও টানেলে পৌঁছায় না। অনুমান না করে প্রকৃত সাবনেট দেখুন:
docker network inspect bridge --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'
ip route get 10.20.30.40
দ্বিতীয়টি MTU সমস্যা। সংযোগ প্রতিষ্ঠিত হয় ও TLS সম্পন্ন হয়, কিন্তু বড় উত্তর আটকে যায়, তাহলে এটি প্যাকেট-আকারের সমস্যা, অনুমোদনের সমস্যা নয়, এবং DNS রেকর্ড বদলে এটি কখনও ঠিক হবে না। কিছু বদলানোর আগে ছোট ও বড় অনুরোধ দিয়ে পরীক্ষা করুন এবং দুটি ফলাফল লিখে রাখুন।
ওভারল্যাপের সমাধান হল ভিন্ন কন্টেইনার সাবনেট বা সীমিত রুট, যা ঠিকানা পরিকল্পনার মালিক বেছে নেবেন। MTU আটকে যাওয়ার সমাধান হল টানেল বা ইন্টারফেসের MTU এমন মানে সীমিত বা কমানো যা পথ পেরিয়ে টিকে থাকে, এবং তা আপনার নিয়ন্ত্রণে থাকা স্তরে প্রয়োগ করা।
প্রক্সি কনফিগারেশন মেশিন নয়, প্রসেসভিত্তিক
কন্টেইনারের ভেতরে localhost সেই কন্টেইনারের নিজের নেটওয়ার্ক প্রেক্ষাপট বোঝায়, তাই হোস্টে চলা প্রক্সি সেখানে ওই নামে পৌঁছানো যায় না। Docker Desktop হোস্ট অ্যাক্সেসের জন্য host.docker.internal দেয়, আর Linux-এ আপনি --add-host=host.docker.internal:host-gateway দিয়ে সেটি স্পষ্টভাবে যোগ করেন। যেভাবেই হোক, ওই নাম আপনাকে হোস্টে একটি রুট দেয়; এটি প্রক্সি পরিষেবা তৈরি করে না, ব্যবহারের অনুমতিও দেয় না।
প্রকৃত পরিবেশের জন্য দেওয়া প্রক্সি ঠিকানা ও পোর্ট ব্যবহার করুন এবং কে সেটি পড়ছে তা দেখুন। ইন্টারঅ্যাকটিভ শেলে এক্সপোর্ট করা ভেরিয়েবল স্বয়ংক্রিয়ভাবে প্রতিটি এডিটর এক্সটেনশন, ল্যাঙ্গুয়েজ সার্ভার, বিল্ড টুল ও ব্যাকগ্রাউন্ড ডেমন কনফিগার করে না। গুরুত্বপূর্ণ হল যে প্রসেস ব্যর্থ অনুরোধটি করেছে, তাই আপনার টার্মিনালের নয়, তার পরিবেশ দেখুন।
শেষে, সমাধানটিকে নিজেকে ব্যাখ্যা করতে দিন। কাজের সমাধান বলে দেয় কোন সীমানাটি ভুল ছিল, কোন সেটিং তা বদলেছে এবং এখন কোন প্রসেসগুলি প্রভাবিত হচ্ছে। VPN, এডিটর ও ইঞ্জিন পরপর রিস্টার্ট করলে উপসর্গ বদলাতে পারে, কিন্তু পরের ব্যক্তির ব্যবহারের মতো কিছু রেখে যায় না।