পাঠ ২৪ · ৫৭-এর মধ্যে · মডিউল ৬
Home / Courses / Cloud Computing & DevOps / কন্টেইনার লাইফসাইকেল

Docker কন্টেইনার লাইফসাইকেল ও নেটওয়ার্কিং

Docker container lifecycle & networking
৮ মিনিট পড়া মধ্যম · Intermediate Python কোডসহ সম্পূর্ণ বাংলায়

এই পাঠে যা শিখবেন

  • একটি কন্টেইনারের সম্ভাব্য স্টেটসমূহ এবং কোন স্টেট থেকে কোন স্টেটে যাওয়া বৈধ
  • কেন কন্টেইনারের ফাইলসিস্টেম পরিবর্তন ডিফল্টভাবে ক্ষণস্থায়ী, এবং ভলিউম কীভাবে এটি সমাধান করে
  • Docker-এর তিনটি নেটওয়ার্কিং মোড এবং প্রতিটি কখন ব্যবহার হয়
  • Python দিয়ে একটি বৈধ স্টেট-ট্রানজিশন ফাংশন লেখা যা অবৈধ ট্রানজিশন সঠিকভাবে প্রত্যাখ্যান করে

১ · কন্টেইনার লাইফসাইকেল — একটি স্টেট মেশিন

একটি Docker কন্টেইনার সবসময় একটি নির্দিষ্ট, সীমিত সংখ্যক স্টেটেরContainer Stateএকটি কন্টেইনারের বর্তমান অবস্থা — created, running, paused, stopped, বা removed-এর একটি। একটির মধ্যে থাকে, এবং একটি স্টেট থেকে অন্য স্টেটে যাওয়া শুধু নির্দিষ্ট, বৈধ অ্যাকশনের মাধ্যমেই সম্ভব — ঠিক যেমন একটি ট্রাফিক লাইট সরাসরি লাল থেকে সবুজ হতে পারে না, একটি নির্দিষ্ট ক্রম অনুসরণ করতে হয়।

created
কন্টেইনার তৈরি হয়েছে (ইমেজ থেকে) কিন্তু এখনো শুরু হয়নি — কোনো প্রসেস চলছে না।
running
কন্টেইনারের প্রধান প্রসেস সক্রিয়ভাবে চলছে।
paused
প্রসেস সাময়িকভাবে স্থগিত (ফ্রিজড) — মেমরিতে থাকে কিন্তু CPU ব্যবহার করে না।
stopped
প্রধান প্রসেস বন্ধ হয়ে গেছে — কন্টেইনার এখনো ডিস্কে বিদ্যমান, আবার শুরু করা যায়।
removed
কন্টেইনার সম্পূর্ণভাবে মুছে ফেলা হয়েছে — একটি টার্মিনাল স্টেট, এখান থেকে আর কোনো অ্যাকশন সম্ভব নয়।

বৈধ ট্রানজিশনগুলো — created → (start) → running → (stop) → stopped → (remove) → removed, এবং running ↔ paused (pause/resume দিয়ে দুই দিকে)। লক্ষণীয়, removed একটি টার্মিনাল স্টেট — একবার একটি কন্টেইনার রিমুভ হয়ে গেলে, সেটিকে আবার running-এ ফেরানোর কোনো বৈধ অ্যাকশন নেই (একটি সম্পূর্ণ নতুন কন্টেইনার তৈরি করা ছাড়া)।

২ · ভলিউম — ক্ষণস্থায়ী ফাইলসিস্টেমের সমাধান

ডিফল্টভাবে, একটি কন্টেইনারের ভেতরে করা যেকোনো ফাইলসিস্টেম পরিবর্তন ক্ষণস্থায়ী (ephemeral) — কন্টেইনার removed স্টেটে গেলে সেই পরিবর্তনসহ পুরো লেখার-যোগ্য লেয়ার হারিয়ে যায় (L23-এর ইমেজ-কন্টেইনার সম্পর্কের সরাসরি ফলাফল — ইমেজ নিজে অপরিবর্তনীয়, তাই মূল ইমেজে কিছু হারায় না, কিন্তু কন্টেইনারের নিজস্ব লেখার-যোগ্য লেয়ার রিমুভের সাথে সাথে চলে যায়)।

ভলিউমVolumeকন্টেইনারের লাইফসাইকেলের বাইরে বিদ্যমান পার্সিস্টেন্ট স্টোরেজ, যা একটি কন্টেইনারের ভেতরে মাউন্ট করা হয় — কন্টেইনার রিমুভ হলেও ভলিউমের ডেটা টিকে থাকে। ডেটাবেসের ফাইল, আপলোড করা ইউজার কনটেন্ট, বা যেকোনো স্টেটফুল ডেটার জন্য ভলিউম আবশ্যক — অন্যথায় একটি সাধারণ কন্টেইনার রিস্টার্ট বা আপডেটেই সব ডেটা হারিয়ে যাবে।

৩ · নেটওয়ার্কিং মোড

bridge (ডিফল্ট)
একই হোস্টের কন্টেইনারগুলো একটি অভ্যন্তরীণ ভার্চুয়াল নেটওয়ার্কের মাধ্যমে একে অপরের সাথে যোগাযোগ করতে পারে, হোস্ট থেকে আইসোলেটেড থেকে।
host
কন্টেইনার হোস্টের নেটওয়ার্ক স্ট্যাক সরাসরি শেয়ার করে — কোনো আইসোলেশন নেই, সর্বোচ্চ পারফরম্যান্স কিন্তু কম নিরাপত্তা।
none
কন্টেইনারের কোনো নেটওয়ার্ক ইন্টারফেসই থাকে না — সম্পূর্ণ আইসোলেটেড, শুধু বিশুদ্ধ কম্পিউট প্রয়োজন হলে ব্যবহৃত হয়।
Python
# কন্টেইনার লাইফসাইকেল — একটি বৈধ স্টেট-ট্রানজিশন মেশিন
# প্রতিটি স্টেট থেকে শুধু নির্দিষ্ট অ্যাকশন-ই বৈধ পরবর্তী স্টেটে নিয়ে যায়
TRANSITIONS = {
    "created": {"start": "running", "remove": "removed"},
    "running": {"pause": "paused", "stop": "stopped"},
    "paused":  {"resume": "running", "stop": "stopped"},
    "stopped": {"start": "running", "remove": "removed"},
    "removed": {},  # টার্মিনাল স্টেট — এখান থেকে কোনো বৈধ অ্যাকশন নেই
}


def transition(current_state, action):
    """বৈধ হলে (True, নতুন_স্টেট) রিটার্ন করে, অবৈধ হলে (False, current_state) — স্টেট অপরিবর্তিত থাকে।"""
    allowed_actions = TRANSITIONS.get(current_state, {})
    if action in allowed_actions:
        return True, allowed_actions[action]
    return False, current_state


# পরিস্থিতি ১: একটি সম্পূর্ণ বৈধ সিকোয়েন্স
state = "created"
sequence = [("start", "রান শুরু"), ("pause", "সাময়িক স্থগিত"),
            ("resume", "আবার চালু"), ("stop", "বন্ধ করা"), ("remove", "মুছে ফেলা")]

print("== বৈধ সিকোয়েন্স ==")
print(f"  প্রাথমিক স্টেট: {state}")
for action, label in sequence:
    ok, state = transition(state, action)
    print(f"  অ্যাকশন={action:8} ({label:12}) -> সফল={ok!s:6} নতুন স্টেট={state}")

# পরিস্থিতি ২: একটি অবৈধ ট্রানজিশন — removed থেকে সরাসরি running-এ যাওয়ার চেষ্টা
print("\n== অবৈধ ট্রানজিশন পরীক্ষা ==")
final_state = state  # এতক্ষণে "removed"
ok, new_state = transition(final_state, "start")
print(f"  স্টেট={final_state}, অ্যাকশন=start -> সফল={ok!s:6} স্টেট={new_state}")
print("  প্রত্যাখ্যাত!" if not ok else "  ভুল করে গ্রহণ হয়ে গেছে — এটি হওয়ার কথা নয়!")

    
লক্ষ্য করুন — removed স্টেটের জন্য TRANSITIONS ডিকশনারিতে কোনো অ্যাকশন সংজ্ঞায়িত নেই (একটি খালি dict), তাই সেই স্টেট থেকে যেকোনো অ্যাকশন (এমনকি start) স্বয়ংক্রিয়ভাবে প্রত্যাখ্যাত হয় — allowed_actions খালি থাকায় action in allowed_actions সবসময় False হবে। এটিই একটি টার্মিনাল স্টেটকে কোডে সঠিকভাবে প্রতিনিধিত্ব করার উপায় — আলাদা কোনো if-শর্ত না লিখেই।
মূল কথা · Key takeaway

কন্টেইনার লাইফসাইকেল একটি কঠোরভাবে সংজ্ঞায়িত স্টেট মেশিন — বৈধ ট্রানজিশনের বাইরে কিছু ঘটতে পারে না। ফাইলসিস্টেম পরিবর্তন ডিফল্টভাবে ক্ষণস্থায়ী (ভলিউম ছাড়া), এবং নেটওয়ার্কিং মোড নির্ধারণ করে একটি কন্টেইনার বাইরের বিশ্বের সাথে কতটা সংযুক্ত থাকবে — এই তিনটি ধারণাই M7-এর Kubernetes Pod/Volume/Service ধারণার সরাসরি ভিত্তি তৈরি করে।

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।

প্র ০১ কেন paused স্টেট থেকে সরাসরি removed-এ যাওয়ার কোনো একক অ্যাকশন নেই, বরং আগে stopped-এ যেতে হয়?

এটি একটি ডিজাইন সিদ্ধান্ত যা নিরাপত্তা নিশ্চিত করে — একটি "paused" কন্টেইনারের প্রসেস এখনো মেমরিতে ফ্রিজড অবস্থায় বিদ্যমান, শুধু সাসপেন্ড করা। রিমুভ করার আগে প্রথমে প্রসেসটি পরিষ্কারভাবে বন্ধ করা (stopped) নিশ্চিত করে যে কোনো চলমান রিসোর্স (ফাইল হ্যান্ডেল, নেটওয়ার্ক কানেকশন) সঠিকভাবে রিলিজ হয়েছে, হঠাৎ একটি ফ্রিজড প্রসেসকে সরাসরি ধ্বংস করার বদলে।

প্র ০২ একটি ডেটাবেস কন্টেইনার চালানোর সময় ভলিউম ব্যবহার না করলে বাস্তবে কী ধরনের সমস্যা হতে পারে?

ডেটাবেসের সব ডেটা কন্টেইনারের লেখার-যোগ্য ফাইলসিস্টেম লেয়ারে সংরক্ষিত হবে। কন্টেইনারটি ক্র্যাশ করলে, আপডেট করার জন্য রিমুভ করলে, বা নতুন ইমেজ দিয়ে প্রতিস্থাপন করলে (L37-এর ডিপ্লয়মেন্ট স্ট্র্যাটেজি) — সেই সব ডেটা স্থায়ীভাবে হারিয়ে যাবে, কারণ কন্টেইনার রিমুভের সাথে সাথে তার লেখার-যোগ্য লেয়ারও মুছে যায়। এটি একটি মারাত্মক ডেটা-লস দৃশ্যকল্প — তাই যেকোনো স্টেটফুল ওয়ার্কলোডের জন্য ভলিউম অপরিহার্য।

প্র ০৩ host নেটওয়ার্কিং মোড সর্বোচ্চ পারফরম্যান্স দেয় কিন্তু কম নিরাপদ কেন — L16-এর নেটওয়ার্ক সিকিউরিটি ধারণার সাথে সম্পর্ক ব্যাখ্যা করুন।

bridge মোডে কন্টেইনারের নিজস্ব আলাদা নেটওয়ার্ক নেমস্পেস থাকে — হোস্টের নেটওয়ার্ক থেকে একটি স্তর আইসোলেশন পাওয়া যায় (L16-এর "একাধিক স্তরের প্রতিরক্ষা" নীতির সাথে সঙ্গতিপূর্ণ)। host মোডে এই আইসোলেশন স্তরটি সম্পূর্ণ বাদ দেওয়া হয় — কন্টেইনার সরাসরি হোস্টের নেটওয়ার্ক ইন্টারফেস ব্যবহার করে, তাই নেটওয়ার্ক প্যাকেট আইসোলেশন লেয়ার পার হওয়ার ওভারহেড থাকে না (দ্রুততর), কিন্তু একটি কম্প্রোমাইজড কন্টেইনার এখন সরাসরি হোস্টের নেটওয়ার্ক দেখতে/ব্যবহার করতে পারে — অ্যাটাক সারফেস বেড়ে যায়।

অনুশীলন

  1. চিন্তা করুন: TRANSITIONS ডিকশনারিতে যদি "stopped": {"start": "running"} শুধু এতটুকুই থাকতো (remove অ্যাকশন বাদ দিয়ে), তাহলে একটি stopped কন্টেইনারকে রিমুভ করার কী উপায় থাকতো?

    কোনো উপায় থাকতো না — transition("stopped", "remove") সবসময় (False, "stopped") রিটার্ন করতো, কারণ "remove" আর allowed_actions-এ নেই। এটি দেখায় স্টেট মেশিনের সংজ্ঞাটিই (dict-এর কনটেন্ট) আসল বৈধতার উৎস — কোডের বাকি অংশ শুধু সেই সংজ্ঞা মেনে চলে, নিজে থেকে কোনো অতিরিক্ত যুক্তি প্রয়োগ করে না।

  2. পরীক্ষা করুন: কোড সেলে একটি নতুন টেস্ট যোগ করুন — transition("paused", "remove") কল করুন এবং ফলাফল দেখুন। এটি কি বৈধ, নাকি প্রত্যাখ্যাত হয়?

    TRANSITIONS["paused"]-এ শুধু "resume" ও "stop" সংজ্ঞায়িত — "remove" নেই, তাই এই কলটি (False, "paused") রিটার্ন করবে। এটি সঠিক আচরণ — একটি paused কন্টেইনারকে সরাসরি রিমুভ করার আগে আগে stop করাতে হবে, যেমনটি উপরের প্র ০১-এ আলোচনা হয়েছে।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

আগের পাঠ
Docker ইমেজ ও Dockerfile