ডেভেলপারদের জন্য Docker: ইমেজ, কন্টেইনার এবং Compose

DevOps2026-10-12TryQuickToolBox

আপনি একটি প্রজেক্ট ক্লোন করেছেন, সেটআপ নির্দেশাবলী চালিয়েছেন, এবং একটি বাধার সম্মুখীন হয়েছেন: একটি অনুপস্থিত সিস্টেম লাইব্রেরি, একটি ডাটাবেস যা শুরু হচ্ছে না, অথবা একটি Node সংস্করণের অমিল। Docker এই ধরনের সমস্যা দূর করার জন্যই বিদ্যমান। আপনার মেশিনে সরাসরি সার্ভিস ইনস্টল করার পরিবর্তে, আপনি সেগুলি একবার বর্ণনা করেন এবং আইসোলেটেড কন্টেইনারে চালান যা সব জায়গায় একইভাবে আচরণ করে।

এই গাইডটি তিনটি ধারণা ব্যাখ্যা করে যা আপনার আসলে প্রয়োজন: ইমেজ, কন্টেইনার, এবং Compose। এটি ব্যবহারিক থাকে, এমন কমান্ড সহ যা আপনি পড়ার সময় চালাতে পারেন।

ইমেজ বনাম কন্টেইনার: মানসিক মডেল

একটি ইমেজ হলো একটি রিড-অনলি টেমপ্লেট। এতে একটি ফাইলসিস্টেম স্ন্যাপশট এবং ডিফল্ট কমান্ড ও এক্সপোজড পোর্টের মতো মেটাডেটা থাকে। একটি কন্টেইনার হলো সেই ইমেজের একটি চলমান (বা বন্ধ) ইনস্ট্যান্স যার উপরে একটি পাতলা রাইটেবল লেয়ার থাকে।

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

ধারণাএটি কীসাধারণ কমান্ড
ইমেজঅপরিবর্তনীয় টেমপ্লেটdocker build, docker pull
কন্টেইনারচলমান ইনস্ট্যান্সdocker run, docker ps
ভলিউমস্থায়ী স্টোরেজdocker volume create
Composeমাল্টি-কন্টেইনার সংজ্ঞাdocker compose up

একটি Dockerfile দিয়ে আপনার প্রথম ইমেজ

একটি Dockerfile হলো একটি রেসিপি। প্রতিটি নির্দেশ একটি লেয়ার তৈরি করে, এবং Docker লেয়ারগুলি ক্যাশ করে যাতে কিছু পরিবর্তন না হলে পুনর্নির্মাণ দ্রুত হয়। এখানে একটি ছোট Node.js উদাহরণ:

FROM node:20-alpine\nWORKDIR /app\nCOPY package*.json ./\nRUN npm ci --omit=dev\nCOPY . .\nEXPOSE 3000\nCMD ["node", "server.js"]

এখানে দুটি অভ্যাস গুরুত্বপূর্ণ। প্রথমত, বাকি সোর্সের আগে ডিপেন্ডেন্সি ম্যানিফেস্ট কপি করুন যাতে শুধুমাত্র অ্যাপ্লিকেশন কোড পরিবর্তন হলে npm ci লেয়ার ক্যাশ হয়। দ্বিতীয়ত, আকার এবং অ্যাটাক সারফেস কমাতে alpine-এর মতো একটি স্লিম বেস ইমেজ পছন্দ করুন।

এটি বিল্ড এবং চালান:

docker build -t myapp:1.0 .\ndocker run --rm -p 3000:3000 myapp:1.0

-p 3000:3000 ফ্ল্যাগটি হোস্ট পোর্ট 3000 কে কন্টেইনার পোর্ট 3000-এ ম্যাপ করে। --rm কন্টেইনারটি বন্ধ হয়ে গেলে মুছে ফেলে, যা ডেভেলপমেন্টের সময় আপনার মেশিন পরিষ্কার রাখে।

প্রতিদিনের কন্টেইনার কমান্ড

এগুলি বেশিরভাগ দৈনন্দিন কাজ কভার করে:

যখন একটি কন্টেইনার সাথে সাথে বন্ধ হয়ে যায়, প্রথমে লগ পড়ুন। সবচেয়ে সাধারণ কারণগুলি হলো ভুল CMD, একটি অনুপস্থিত এনভায়রনমেন্ট ভেরিয়েবল, অথবা কন্টেইনারের ভিতরে প্রসেসটি 0.0.0.0 এর পরিবর্তে 127.0.0.1-এ বাইন্ড করা।

Compose কেন বিদ্যমান

একটি বাস্তব অ্যাপ্লিকেশনের সাধারণত একাধিক প্রসেস প্রয়োজন: একটি API, একটি ডাটাবেস, হয়তো একটি ক্যাশে। দীর্ঘ ফ্ল্যাগ তালিকা সহ তিনটি docker run কমান্ড চালানো ত্রুটি-প্রবণ। Docker Compose আপনাকে একটি YAML ফাইলে সমস্ত সার্ভিস ঘোষণা করতে এবং সেগুলি একসাথে শুরু করতে দেয়।

services:\n  api:\n    build: .\n    ports:\n      - "3000:3000"\n    environment:\n      DATABASE_URL: postgres://app:secret@db:5432/app\n    depends_on:\n      - db\n  db:\n    image: postgres:16-alpine\n    environment:\n      POSTGRES_USER: app\n      POSTGRES_PASSWORD: secret\n      POSTGRES_DB: app\n    volumes:\n      - db_data:/var/lib/postgresql/data\nvolumes:\n  db_data:

লক্ষ্য করুন যে API db-এর সাথে সংযুক্ত হয়, localhost-এর সাথে নয়। Compose একটি প্রাইভেট নেটওয়ার্ক তৈরি করে যেখানে প্রতিটি সার্ভিস তার সার্ভিস নাম দ্বারা পৌঁছানো যায়। এটি নতুনদের জন্য বিভ্রান্তির একক সবচেয়ে সাধারণ উৎস।

docker compose up দিয়ে সবকিছু শুরু করুন, অথবা ব্যাকগ্রাউন্ডে চালানোর জন্য docker compose up -d। কোড পরিবর্তনের পরে docker compose up --build দিয়ে পুনর্নির্মাণ করুন। docker compose down দিয়ে টিয়ার ডাউন করুন, এবং যদি আপনি নামযুক্ত ভলিউমগুলিও মুছতে চান তবে -v যোগ করুন।

ভলিউম, বাইন্ড মাউন্ট এবং লাইভ রিলোড

কন্টেইনারগুলি ক্ষণস্থায়ী; সেগুলির ভিতরের ডেটা সরিয়ে ফেললে অদৃশ্য হয়ে যায়। দুটি প্রক্রিয়া এটি সমাধান করে:

  1. নামযুক্ত ভলিউম — Docker দ্বারা পরিচালিত, ডাটাবেস ফাইলের জন্য আদর্শ। এগুলি কন্টেইনার পুনরায় চালু করার পরেও স্থায়ী হয় এবং volumes: বিভাগে ঘোষণা করা হয়।
  2. বাইন্ড মাউন্ট — একটি হোস্ট ডিরেক্টরি কন্টেইনারে ম্যাপ করে, ডেভেলপমেন্টের সময় সোর্স কোডের জন্য আদর্শ।
services:\n  api:\n    build: .\n    volumes:\n      - ./src:/app/src

একটি বাইন্ড মাউন্টের সাথে, আপনার হোস্টে ফাইল সম্পাদনা কন্টেইনারের ভিতরে প্রতিফলিত হয়। এটি একটি ফাইল ওয়াচারের (nodemon, uvicorn --reload, air) সাথে একত্রিত করুন এবং আপনি ইমেজ পুনর্নির্মাণ ছাড়াই লাইভ রিলোড পাবেন।

একটি ব্যবহারিক ডেভেলপমেন্ট ওয়ার্কফ্লো

  1. আপনার অ্যাপের জন্য একটি Dockerfile লিখুন এবং এটি ন্যূনতম রাখুন।
  2. অ্যাপ এবং তার ডিপেন্ডেন্সি সহ একটি docker-compose.yml যোগ করুন।
  3. সোর্স কোডের জন্য বাইন্ড মাউন্ট এবং ডেটার জন্য নামযুক্ত ভলিউম ব্যবহার করুন।
  4. সিক্রেট ফাইল থেকে দূরে রাখুন; একটি .env ফাইল ব্যবহার করুন এবং ${VAR} দিয়ে ভেরিয়েবল রেফারেন্স করুন।
  5. node_modules, .git, এবং বিল্ড আউটপুট ধারণকারী একটি .dockerignore যোগ করুন বিল্ড গতি বাড়ানোর জন্য।
  6. docker compose up --build চালান এবং পুনরাবৃত্তি করুন।

যদি আপনার সার্ভিস লগ তৈরি করে যা আপনার পরে পরিদর্শন করতে হয়, মনে রাখবেন কন্টেইনার লগগুলি শুধু টেক্সট। সার্ভার লগ পার্স করে এমন টুলস, যেমন একটি nginx log analyzer, কন্টেইনারগুলির সাথে ভালভাবে জোড়া লাগে কারণ আপনি হোস্টে কিছু ইনস্টল না করেই লগ পাইপ বা কপি করতে পারেন।

সাধারণ সমস্যা

সাধারণ প্রশ্নোত্তর

একটি ইমেজ এবং একটি কন্টেইনারের মধ্যে পার্থক্য কী?

একটি ইমেজ হলো একটি অপরিবর্তনীয় টেমপ্লেট যা একটি ফাইলসিস্টেম এবং মেটাডেটা ধারণ করে। একটি কন্টেইনার হলো সেই ইমেজের একটি চলমান ইনস্ট্যান্স যার একটি অতিরিক্ত রাইটেবল লেয়ার রয়েছে। আপনি একটি ইমেজ থেকে অনেক কন্টেইনার শুরু করতে পারেন।

একটি একক সার্ভিসের জন্য আমার কি Docker Compose প্রয়োজন?

না। একটি কন্টেইনারের জন্য একটি docker run কমান্ডই যথেষ্ট। Compose মূল্যবান হয়ে ওঠে যখন আপনার একাধিক সার্ভিস, শেয়ার্ড নেটওয়ার্ক, বা এনভায়রনমেন্ট ভেরিয়েবল থাকে যা আপনি এক জায়গায় ঘোষণা করতে চান।

কন্টেইনারগুলি একে অপরের সাথে কীভাবে যোগাযোগ করে?

Compose সমস্ত সার্ভিসকে একটি শেয়ার্ড নেটওয়ার্কে রাখে যেখানে প্রতিটি সার্ভিস তার সার্ভিস নাম দ্বারা পৌঁছানো যায়। সেই নামটি হোস্টনাম হিসেবে ব্যবহার করুন, উদাহরণস্বরূপ db:5432, localhost-এর পরিবর্তে।

Docker একটি ছোট প্রাথমিক বিনিয়োগের পুরস্কার দেয়। একবার ইমেজ, কন্টেইনার এবং Compose বুঝে গেলে, একজন টিমমেটকে অনবোর্ড করা বা মেশিন পরিবর্তন করা একটি সেটআপ আচার হওয়া বন্ধ করে এবং একটি একক কমান্ড হয়ে যায়।