VPN সংযোগের পর Docker ভলিউম মাউন্ট ব্যর্থ হয়: daemon পরীক্ষা করুন
আপনার bind mount ঠিক আছে। VPN বদলে দেয় কোন daemon ক্লায়েন্টকে উত্তর দেবে, তাই endpoint ছাপুন, সেখানে পথটি প্রমাণ করুন, আর ভলিউম সম্পাদনা করা বন্ধ করুন।
এই সমস্যার প্রায় প্রতিটি লেখা ভলিউমকে দোষ দেয়, আর ঠিক সেজন্যই সমাধানটি এত সময় নেয়। আপনার একটি bind mount কাজ করছিল, কর্পোরেট VPN সংযুক্ত হলো, এবং docker compose up এখন অনুপস্থিত source path, খালি ডিরেক্টরি, বা ইঞ্জিন যে mount তৈরি করতে অস্বীকার করে তা নিয়ে ব্যর্থ হচ্ছে। আমি যে ইউনিটগুলো পরিষ্কার করেছি সেগুলোতে Compose ফাইল বদলায়নি এবং পথটি সঠিক ছিল। যা বদলেছিল তা হলো কোন daemon অনুরোধটি পেয়েছে, আর mount ত্রুটিটি ছিল কেবল সেই পার্থক্য যেখানে প্রথম দৃশ্যমান হলো।
ভলিউম কখনও সরেনি; অনুরোধটি সরেছে
একটি -v /srv/app:/app ফ্ল্যাগ আপনার shell যে ডিরেক্টরি কপি করে তা নয়। ক্লায়েন্ট এটিকে API অনুরোধে পরিণত করে, আর যে daemon উত্তর দেয় সে /srv/app নিজের ফাইলসিস্টেমের বিপরীতে সমাধান করে। যখন দুই পক্ষই একই কার্নেলে চলে, সেই পথটিই আপনার ফাইল ম্যানেজারে দেখা যায়। যখন endpoint বদলায়, একই স্ট্রিং এমন মেশিনে খোঁজা হয় যা কখনও আপনার প্রকল্প ডিরেক্টরির কথা শোনেনি, আর daemon হয় source অনুপস্থিত বলে জানায়, নয়তো চুপচাপ তার জায়গায় একটি খালি ডিরেক্টরি তৈরি করে।
এজন্যই একটি named volume কাজ করতে থাকে, অথচ bind mount করে না। -v appdata:/app daemon-এর মালিকানাধীন স্টোরেজের নাম দেয়, তাই কোনো host path-কে নির্দিষ্ট কোনো জায়গায় থাকতে হয় না। যদি একটি সার্ভিসকে bind mount থেকে named volume-এ বদলে দিলে ত্রুটি মিলিয়ে যায়, তাহলে আপনি সমস্যার সমাধান করেননি। আপনি নিশ্চিত করেছেন যে ক্লায়েন্ট ও daemon একমত নয় পথটি কোন ফাইলসিস্টেমের, আর আপনি আবার সত্যিকারের host ডিরেক্টরি চাইলেই সেই মতবিরোধ ফিরে আসে।
মাউন্টে হাত দেওয়ার আগে endpoint ছাপুন
কয়েকটি সেটিং ক্লায়েন্টকে একটি endpoint-এর দিকে নির্দেশ করতে পারে, আর তারা সবসময় একমত হয় না: --context ফ্ল্যাগ, DOCKER_CONTEXT, DOCKER_HOST বর্তমান shell-এ, এবং ক্লায়েন্ট কনফিগারেশনে সংরক্ষিত context। অগ্রাধিকার নিয়ে ভাবনার বদলে সবগুলো ছাপুন এবং উত্তরগুলো তুলনা করুন।
docker context show
docker context ls
docker version
docker info --format "{{.Name}} {{.OperatingSystem}} {{.ServerVersion}}"
ক্লায়েন্ট কনফিগ থাকে ~/.docker/config.json Linux ও macOS-এ এবং %USERPROFILE%\.docker\config.json Windows-এ, আর বর্তমান টার্মিনালে export করা মান সংরক্ষিত মানটিকে কেবল সেই সেশনেই ছাড়িয়ে যায়। যদি endpoint স্থানীয় socket-এর বদলে hostname হয়, নাম সমাধান ও রুট ঠিক করে এটি কোথায় পৌঁছাবে, আর VPN ক্লায়েন্ট ঠিক সেগুলোই পুনর্লিখন করে। যে tunnel একটি রুট যোগ করে বা resolver বদলায়, সে এমন একটি নাম যা আগে এই ল্যাপটপ বোঝাত তা কর্পোরেট নেটওয়ার্কের ভেতরের ঠিকানায় পাঠাতে পারে।
কনফিগারেশনের বদলে অবস্থা তুলনা করুন। চালান docker ps -a এবং docker images tunnel বন্ধ রেখে, তারপর আবার চালু রেখে। ভিন্ন কন্টেইনার তালিকা যেকোনো কনফিগ ফাইলের চেয়ে শক্তিশালী প্রমাণ, কারণ এটি দেখায় যে ভিন্ন একটি daemon আপনার অনুরোধের উত্তর দিয়েছে।
daemon-কে জিজ্ঞাসা করুন পথটি সেখানে আছে কি না
কোন daemon-এ পৌঁছেছেন জেনে গেলে, তাকে ডিরেক্টরিটি দেখতে বলুন। --mount ফর্মটি সংক্ষিপ্ত ফ্ল্যাগের চেয়ে স্পষ্ট বার্তায় ব্যর্থ হয়, কারণ এটি কন্টেইনার চালু করার আগেই source যাচাই করে:
docker run --rm --mount type=bind,source=/srv/app,target=/app alpine ls -la /app
যদি এটি source অনুপস্থিত বলে জানায়, যে মেশিন উত্তর দিয়েছে সেখানে এটি তৈরি করুন, অথবা সার্ভিসটিকে একটি named volume-এ নির্দেশ করে ডেটা সেখানে কপি করুন। যা করা উচিত নয় তা হলো এই পরীক্ষার আগে ভলিউম পুনরায় তৈরি করা এবং ইঞ্জিন পুনরায় ইনস্টল করা। সেই কাজগুলো পরিবেশকে যথেষ্ট বদলে দেয় যাতে অসঙ্গতিটি লুকিয়ে যায়, অথচ সেটি জায়গাতেই থাকে।
আরও একটি পথ সম্পূর্ণ ভিন্ন জায়গায় চলে: image টানা daemon-এর কাজ, ক্লায়েন্টের নয়। সফলভাবে টানা কেবল প্রমাণ করে daemon একটি registry-তে পৌঁছাতে পারে, আর কাজ করা bind mount কেবল প্রমাণ করে একটি পথ সমাধান হয়েছে। প্রতিটি পথ যেখানে সত্যিই চলে সেখানেই পরীক্ষা করুন, নইলে ভুলটির পেছনে একটি দুপুর নষ্ট হবে।
ইন্ট্রানেট নাম ব্যর্থ হয় ভিন্ন কারণে
একই প্রতিবেদনের দ্বিতীয় অংশটি সাধারণত হলো কন্টেইনার intranet.corp.example-এ পৌঁছাতে পারে না। এটি আলাদা একটি প্রক্রিয়া, দ্বিতীয় ভলিউম সমস্যা নয়। কন্টেইনার তার /etc/resolv.conf শুরু হওয়ার সময় পায়, যা daemon resolver সেটিংস থেকে তৈরি হয়, তাই কন্টেইনার তৈরির পরে VPN যে DNS সার্ভার যোগ করেছে তা কন্টেইনার পুনরায় তৈরি না হওয়া পর্যন্ত সেখানে দেখা যাবে না।
ব্যবহারকারী-নির্ধারিত নেটওয়ার্কে Docker-এর অন্তর্নির্মিত resolver বাইরের অনুসন্ধান host-এর কনফিগার করা সার্ভারগুলোতে পাঠায়, যা সাহায্য করে যখন VPN host resolver পুনর্লিখন করে এবং ক্ষতি করে যখন split DNS একটি অভ্যন্তরীণ zone এমন সার্ভারে পাঠায় যা daemon আর দেখে না। সংকীর্ণ, স্পষ্ট ম্যাপিং কখনও না বদলানো নামগুলোর জন্য এই বিতর্ক এড়িয়ে যায়:
services:
web:
extra_hosts:
- "intranet.corp.example:10.20.30.40"
এটি কন্টেইনারের hosts ফাইলে একটি এন্ট্রি লেখে, তাই কন্টেইনার tunnel সম্পর্কে কিছুই জানতে পারে না, এবং এটি ঠিকানাটিও জমিয়ে দেয়। অভ্যন্তরীণ host সরে গেলে এন্ট্রিটি ভুলই থাকে যতক্ষণ না কেউ Compose ফাইল সম্পাদনা করে। স্থির অ্যাপ্লায়েন্স বা পিন করা ডেটাবেসের জন্য এটি ব্যবহার করুন, আর যে নামগুলো সরে যায় সেগুলো DNS-কে সামলাতে দিন।
পুনরায় ইনস্টল আসলে কী বদলায়
Docker Desktop পুনরায় ইনস্টল করলে VM, socket ও context তালিকা নতুন করে তৈরি হয়, আর mount আবার কাজ করতে শুরু করে। সেই ফলাফল সত্যি এবং এটি কিছু শেখায় না, এজন্যই পরের VPN আপডেটের পরে একই ব্যর্থতা ফিরে আসে। পুনরায় ইনস্টল ক্লায়েন্ট যে endpoint ব্যবহার করছিল তা বদলে দিয়েছে; এটি আপনার প্রকল্প যে পথের নাম দেয় আর daemon যে ফাইলসিস্টেম সত্যিই পড়ে তাদের মধ্যে মিল করেনি।
আমার কাজের ক্রম সংক্ষিপ্ত। নিশ্চিত করুন ক্লায়েন্ট কোন endpoint ব্যবহার করবে। কন্টেইনার তালিকা তুলনা করে নিশ্চিত করুন কোন daemon উত্তর দিয়েছে। সেই daemon-কে source path তালিকাভুক্ত করতে বলুন। কেবল তারপরেই mount সম্পাদনা করুন, hosts এন্ট্রি যোগ করুন, বা ভলিউমের ধরন বদলান। যদি আপনি এমন দলের জন্য Compose ফাইল রক্ষণাবেক্ষণ করেন যারা VPN-এর ওপর কাজ করে, তবে daemon-এর মালিকানা উচিত এমন ডেটার জন্য named volume পছন্দ করুন, যাতে host path কখনও চুক্তির অংশ না হয়।