আপনার মেশিনে সহজে রিজলভ হওয়া একটি প্রাইভেট প্যাকেজ বিল্ডের ভিতরে 404 বা টাইমআউট দিয়ে ব্যর্থ হতে পারে, আর Dockerfile খুব কমই এর কারণ। বিল্ড ধাপটি চলে ভিন্ন নেটওয়ার্ক নেমস্পেসে, ভিন্ন DNS দৃষ্টিভঙ্গি ও ভিন্ন ক্রেডেনশিয়াল স্টোর নিয়ে, যা আপনি যে শেলে পরীক্ষা করেছিলেন তার থেকে আলাদা। এই যাচাইগুলো ক্রমানুসারে করুন এবং প্রথম যেটি ব্যর্থ হয় সেখানেই থামুন, কারণ প্রতিটি পরের যাচাই ধরে নেয় আগেরটি পাশ করেছে। প্রতিটি ধাপ সেই কমান্ডের নাম বলে দেয় যা বিষয়টি নিষ্পত্তি করে।

Dockerfile নয়, শুরু করুন builder-এর নাম দিয়ে

BuildKit লোকাল, কনটেইনারাইজড বা অন্য মেশিনে চলতে পারে, এবং প্রতিটির নিজস্ব ডিফল্ট নেটওয়ার্ক আছে। চালান docker buildx ls এবং কিছু পরিবর্তন করার আগে তারা চিহ্নিত নোডটি পড়ুন। একটি docker-container ড্রাইভার বা ক্লাউড বিল্ডার শুধু আপনি সেখানে কমান্ডটি টাইপ করেছেন বলে আপনার ল্যাপটপের প্রাইভেট রুট শেয়ার করে না। যদি সক্রিয় বিল্ডার দূরের হয়, তবে বাকি প্রতিটি যাচাই আপনার ওয়ার্কস্টেশনের বদলে সেই হোস্টের বিরুদ্ধে চালাতে হবে।

বিল্ডার নিজের রিজলভার কনফিগারেশন ও প্রক্সি ভেরিয়েবলওবহন করে। দুটোই বিল্ডের সময় পড়া হয় এবং যে টার্মিনাল বিল্ড শুরু করেছে তার থেকে উত্তরাধিকারসূত্রে আসে না।

বিল্ড ধাপের ভিতর থেকে নেটওয়ার্ক পথ প্রমাণ করুন

একটি অস্থায়ী স্টেজ লিখুন যা ডিপেন্ডেন্সি হোস্ট রিজলভ করে এবং তার সঙ্গে সংযোগ খোলে। আপনার শেলের জন্য নয়, বরং বিল্ডারের জন্য প্রশ্নটির উত্তর দেয় কেবল এই পরীক্ষাটিই।

FROM alpine:3.20
RUN apk add --no-cache curl bind-tools  && getent hosts registry.example.internal  && curl -sS -o /dev/null -w "%{http_code}
" https://registry.example.internal/simple/

আপনার আসল বিল্ড যে builder, নেটওয়ার্ক মোড ও secret মাউন্ট ব্যবহার করে, সেগুলো দিয়েই ফাইলটি বিল্ড করুন: docker buildx build --builder remote0 -f Dockerfile.probe --progress=plain .. যদি getent কিছু না ছাপায়, তবে সমস্যা নাম রিজলভিংয়ে এবং কোনো ক্রেডেনশিয়াল তা সারাবে না। নাম রিজলভ হলে কিন্তু curl টাইমআউট জানায়, তবে বাধা হলো রুট বা রেজিস্ট্রির সামনের ইগ্রেস নীতি।

প্রোব উত্তর দেওয়ার পরেই তা মুছে ফেলুন। এটি একটি ডায়াগনস্টিক স্টেজ, এটিকে কখনো ট্যাগ বা পুশ করা উচিত নয়।

ক্রেডেনশিয়াল কপি না করে মাউন্ট করুন

পথ কাজ করার পর, পরের ব্যর্থতা হলো প্রমাণীকরণ। BuildKit secret মাউন্ট একটি ফাইলকে একটি RUN ধাপে উন্মুক্ত করে, সেটি কোনো লেয়ারে না লিখেই; ডিপেন্ডেন্সি টুলের যা দরকার এবং ইমেজের যা রাখা উচিত নয়, তা-ই এটি।

RUN --mount=type=secret,id=npmrc,target=/root/.npmrc     npm ci --omit=dev

secret টি Dockerfile-এর বাইরে থেকে সরবরাহ করতে হবে: docker buildx build --secret id=npmrc,src=/home/me/.npmrc .. ফাইলটি ক্লায়েন্টেই থাকে এবং কখনো ইমেজ ইতিহাসে ঢোকে না। একই টোকেন ধরে রাখা একটি ARG বা ENV এই কাজটি করে না, কারণ দুটোই ইমেজ কনফিগারেশনে রেকর্ড হয়।

নন-রুট ইমেজের নিজস্ব টার্গেট পথ দরকার, যেমন /home/app/.npmrc বা pip, Maven বা Cargo-র সমতুল্য ফাইল। মাউন্ট টার্গেটকে কমান্ড চালানো ব্যবহারকারীর সঙ্গে মিলতে হবে, নইলে টুল এমন একটি কনফিগারেশন ফাইল অনুপস্থিত বলে জানাবে যা আসলে আছে।

ডিপেন্ডেন্সি টুল ইমেজে কী রেখে যায় তা খতিয়ে দেখুন

অস্থায়ী মাউন্ট ক্রেডেনশিয়ালকে লেয়ারের বাইরে রাখে, কিন্তু টুলকে অন্য কিছু লিখতে বাধা দেয় না। প্যাকেজ ম্যানেজাররা lock ফাইল, ক্যাশ ডিরেক্টরি এবং কখনো রিজলভ হওয়া রেজিস্ট্রি URL রেখে যায়।

Dockerfile-এ ভরসা না করে চূড়ান্ত ফাইলসিস্টেম পড়ুন। docker history --no-trunc image:tag প্রতিটি লেয়ার কমান্ড তালিকাভুক্ত করে, আর docker run --rm image:tag sh -c "ls -a /root" চলমান কনটেইনারে কী টিকে গেছে তা দেখায়। এমনকি ফাইলটি কেবল মাউন্ট করা হলেও, লগ লাইনে লেখা একটি টোকেন npm ci চালানোর সময়েই ফাঁস হিসেবেই থাকে।

বিল্ড লগও পড়ুন, কারণ --progress=plain কমান্ডের আউটপুট হুবহু ছাপে। টোকেন সেখানে দেখা গেলে, অন্য কিছুর আগে তা রোটেট করুন এবং এমন ফাইলের মাধ্যমে পাঠান যা টুলটি নিঃশব্দে পড়ে।

রানটাইম ইমেজের আর প্রাইভেট পথ দরকার নেই তা যাচাই করুন

বিল্ড ও চলমান অ্যাপ্লিকেশন একই ডিপেন্ডেন্সির দুটি আলাদা ভোক্তা, এবং কেবল প্রথমটিরই প্রাইভেট রুট দরকার। সম্পূর্ণ ইমেজের উচিত build-কালীন ক্রেডেনশিয়াল ছাড়াই চালু হওয়া, রানটাইম ডিপেন্ডেন্সি রিজলভ করা এবং ট্রাফিক পরিবেশন করা।

যেখানে প্রাইভেট রেজিস্ট্রি নাগালের বাইরে সেখানে এটি পরীক্ষা করুন, বা কনটেইনারটি শুধু --network none দিয়ে চালু করে দেখুন যে মাউন্ট করা secret ছাড়াই এটি বুট হয়। যে কনটেইনার কেবল build secret থাকলেই চালু হয়, সেটি এখনো build পরিবেশের সঙ্গে বাঁধা।

কনটেইনারের সত্যিই রানটাইমে রেজিস্ট্রি দরকার হলে সেটি আলাদা অ্যাক্সেস সিদ্ধান্ত, এবং তার জায়গা build-এ নয়, অর্কেস্ট্রেটরের secret স্টোরে। দুটি পথ আলাদা করে লিখে রাখুন যাতে কেউ build ফ্ল্যাগ দিয়ে রানটাইম পুল সারাতে না যায়। পাঁচটি যাচাই যখন সবগুলো পাশ করে, তখন মূল উপসর্গের প্রতিটি স্তরে একটি নামকরা কারণ থাকে, Docker নেটওয়ার্কিং নিয়ে অনুমান নয়।

সম্পর্কিত নিবন্ধ