ডকারে কমান্ড লিখে ইমেজ তৈরি করা সহজ হলেও, docker build ব্যাকগ্রাউন্ডে কীভাবে কাজ করে এবং কেন কিছু বিল্ড চোখের পলকে হয়ে যায় আর কিছু বিল্ডে দীর্ঘ সময় লাগে—তা জানা একজন দক্ষ ইঞ্জিনিয়ার বা DevOps প্রফেশনালের জন্য অত্যন্ত জরুরি।
এই ব্লগে আমরা ডকারফাইল বিল্ডের অভ্যন্তরীণ জীবনচক্র, টেম্পোরারি কন্টেইনার মেকানিজম, ইন্টারমিডিয়েট লেয়ার এবং ডকার ক্যাশিংয়ের আসল কৌশল বিস্তারিতভাবে উন্মোচন করব।
১. ডকার বিল্ডের অভ্যন্তরীণ জীবনচক্র (Internal Execution Lifecycle)
যখন টার্মিনালে docker build -t go_server:1.0.0 . কমান্ড দেওয়া হয়, ডকার প্রতিটি লাইনের জন্য নিচের ৪টি ধাপ চক্রাকারে সম্পন্ন করে:
┌────────────────────────────────────────────────────────────────────────┐
│ প্রতিটি লাইনের এক্সিকিউশন সাইকেল │
├────────────────────────────────────────────────────────────────────────┤
│ ধাপ ১: পূর্ববর্তী লেয়ারের ইমেজ থেকে টেম্পোরারি কন্টেইনার তৈরি করা │
│ ধাপ ২: বর্তমান ইনস্ট্রাকশনটি সেই কন্টেইনারের ভেতর এক্সিকিউট করা │
│ ধাপ ৩: কন্টেইনারের পরিবর্তনগুলো কমিট করে নতুন ইন্টারমিডিয়েট ইমেজ তৈরি │
│ ধাপ ৪: টেম্পোরারি কন্টেইনারটি স্বয়ংক্রিয়ভাবে মুছে ফেলা (Remove) │
└────────────────────────────────────────────────────────────────────────┘
২. ডকারফাইলের প্রতিটি লাইনের লেয়ার আর্কিটেকচার
একটি সাধারণ ডকারফাইলের প্রতিটি লাইন কীভাবে একেকটি পৃথক লেয়ার তৈরি করে, তা নিচের ডায়াগ্রামে লক্ষ্য করুন:
Dockerfile Instruction Internal State & Layer Creation
───────────────────────────────────────────────────────────────────────────────
FROM ubuntu:24.04 ──▶ [Layer 0 (Base Image)] ──▶ উবুন্টু বেজ ইমেজ পুল/লোড হয়
│
RUN apt update ──▶ [Layer 1 Image] ───────▶ টেম্পোরারি কন্টেইনার ──▶ apt update ──▶ Commit ──▶ Delete Container
│
RUN apt install -y golang ──▶ [Layer 2 Image] ───────▶ টেম্পোরারি কন্টেইনার ──▶ Go Install ──▶ Commit ──▶ Delete Container
│
WORKDIR /app ──▶ [Layer 3 Image] ───────▶ টেম্পোরারি কন্টেইনার ──▶ /app সেট ───▶ Commit ──▶ Delete Container
│
COPY ./server.go ./ ──▶ [Layer 4 Image] ───────▶ টেম্পোরারি কন্টেইনার ──▶ ফাইল কপি ────▶ Commit ──▶ Delete Container
│
CMD ["go", "run", "server.go"] ────────────┴───────────▶ CMD মেটাডাটা বাইন্ড হয়ে ফাইনাল ইমেজ তৈরি
লেয়ারভিত্তিক বিস্তারিত বিশ্লেষণ:
-
Layer 0 (
FROM ubuntu:24.04): ডকার হাব থেকে উবুন্টু ইমেজ পুল করে লোকাল ক্যাশে রাখে এবং বিল্ডের প্রাথমিক রেফারেন্স পয়েন্ট হিসেবে নেয়। -
Layer 1 (
RUN apt update): Layer 0 থেকে একটি টেম্পোরারি কন্টেইনার বানায়, তার ভেতরapt updateকমান্ড চালায়, পরিবর্তিত স্টেটকে কমিট করে Layer 1 ইমেজ তৈরি করে এবং কন্টেইনারটি ডিলিট করে দেয়। -
Layer 2 (
RUN apt install -y golang): Layer 1 থেকে নতুন কন্টেইনার খুলে Golang ইনস্টল করে, আবার কমিট করে Layer 2 ইমেজ তৈরি করে। -
Layer 3 (
WORKDIR /app): Layer 2 থেকে কন্টেইনার খুলে/appডিরেক্টরি সেট ও তৈরি করে Layer 3 ইমেজ তৈরি করে। -
Layer 4 (
COPY ./server.go ./): হোস্ট মেশিন থেকে কোড এনে কন্টেইনারে রেখে কমিট করে Layer 4 ইমেজ তৈরি করে। -
Final Image: সবার শেষে
CMDনির্দেশিকাটি Layer 4-এর সাথে বাইন্ড হয়ে আমাদের কাঙ্ক্ষিত ট্যাগযুক্ত ইমেজ (যেমন:go_server:1.0.0) হিসেবে প্রস্তুত হয়।
৩. ডকার লেয়ার ক্যাশিংয়ের ম্যাজিক (Docker Layer Caching)
ডকার বিল্ডের সবচেয়ে বড় শক্তি হলো এর লেয়ার ক্যাশিং (Layer Caching)। প্রতিবার পুরো ডকারফাইল প্রথম থেকে বিল্ড করার পরিবর্তে ডকার অপরিবর্তিত লেয়ারগুলোকে লোকাল ক্যাশ থেকে পুনরায় ব্যবহার করে।
┌────────────────────────────────────────────────────────────────────────┐
│ ডকারফাইল ক্যাশিং আচরণ │
├────────────────────────────────────────────────────────────────────────┤
│ FROM ubuntu:24.04 [কোনো পরিবর্তন নেই] ──▶ CACHED (0.0s) │
│ RUN apt update [কোনো পরিবর্তন নেই] ──▶ CACHED (0.0s) │
│ RUN apt install -y golang [কোনো পরিবর্তন নেই] ──▶ CACHED (0.0s) │
│ │
│ ───────▶ [ এখানে পরিবর্তন ঘটলে (Cache Invalidation) ] ◀──────── │
│ │
│ WORKDIR /habib [পরিবর্তিত লাইন] ──▶ NEW BUILD (কন্টেইনার)│
│ COPY ./server.go ./ [পরবর্তী সব লাইন] ──▶ NEW BUILD (পুনরায়) │
└────────────────────────────────────────────────────────────────────────┘
ক্যাশ ইনভ্যালিডেশনের মূল নীতি:
- ডকার উপর থেকে নিচ পর্যন্ত প্রতিটি লাইন যাচাই করে।
- যতক্ষণ পর্যন্ত কোনো পরিবর্তন না পাওয়া যায়, ততক্ষণ সব লেয়ার সরাসরি ক্যাশ থেকে গ্রহণ করে।
- যে লাইনে পরিবর্তন শনাক্ত হয়, ঠিক সেই লাইন এবং তার নিচের সমস্ত ইনস্ট্রাকশনের ক্যাশ বাতিল হয়ে যায় এবং সেগুলো নতুন করে সম্পূর্ণ প্রক্রিয়ার মাধ্যমে বিল্ড হয়।
৪. প্রোডাকশন ডকারফাইল অপ্টিমাইজেশন স্ট্র্যাটেজি
প্রোডাকশন এনভায়রনমেন্টে একটি ডকারফাইল শত শত লাইনের হতে পারে। ভুলভাবে ডকারফাইল সাজালে একটি সাধারণ কোড পরিবর্তনের কারণেও ৪০-৫০ মিনিট পর্যন্ত অপ্রয়োজনীয় বিল্ড টাইম লাগতে পারে।
┌────────────────────────────────────────────────────────┐
│ ডকারফাইল সাজানোর মূল নিয়ম │
├────────────────────────────────────────────────────────┤
│ [উপরে] অপরিবর্তনশীল ও ভারী লেয়ার (OS, Runtime, SDK) │
│ │ │
│ ▼ │
│ [মাঝখানে] ডিপেন্ডেন্সি তালিকা (package.json / go.mod) │
│ │ │
│ ▼ │
│ [নিচে] ঘনঘন পরিবর্তিত সোর্স কোড (server.go / src/) │
└────────────────────────────────────────────────────────┘
বেস্ট প্র্যাকটিস:
-
ওএস ও ভারী প্যাকেজ উপরে রাখুন: যেমন
RUN apt updateবা রানটাইম ইনস্টলেশন একদম উপরে রাখা উচিত, কারণ এগুলোতে ঘনঘন হাত দেওয়ার প্রয়োজন হয় না। -
সোর্স কোড নিচে রাখুন: অ্যাপ্লিকেশন কোড (
COPY . .) ডেভেলপাররা প্রতিনিয়ত পরিবর্তন করেন। তাই কোড কপি করার লাইনটি ডকারফাইলের নিচের দিকে রাখা উচিত, যেন উপরের ভারী ডিপেন্ডেন্সিগুলোর ক্যাশ অক্ষত থাকে এবং বিল্ড কয়েক সেকেন্ডের মধ্যে শেষ হয়।
সংক্ষেপ চিত্র (Cheat Sheet)
-
ইন্টারমিডিয়েট ইমেজ: প্রতিটি
RUN,COPY,WORKDIRব্যাকগ্রাউন্ডে একটি করে ইন্টারমিডিয়েট ইমেজ লেয়ার তৈরি করে। - টেম্পোরারি কন্টেইনার: লেয়ারের কমান্ড এক্সিকিউট করতে ডকার ক্ষণস্থায়ী কন্টেইনার তৈরি করে এবং কাজ শেষে তা নিজে থেকেই ডিলিট করে দেয়।
- ক্যাশ সেভ: যে লাইনে পরিবর্তন আসে, তার নিচের সব লেয়ার নতুন করে বিল্ড হয়; উপরের লেয়ারগুলো অক্ষত থাকে।