Docker Compose-এ মেমোরি লিমিট সেট করার নিয়ম
Docker Compose-এ deploy.resources ব্যবহার করে মেমোরি লিমিট সেট করুন। এতে আপনার কন্টেইনার সার্ভারের সব RAM দখল করতে পারবে না এবং exit 137 ত্রুটি এড়াতে সাহায্য করবে।
Docker Compose memory limit যা করে
Docker Compose memory limit হলো একটি কঠোর সীমা যা Linux kernel কোনো কন্টেইনারের cgroup-এর (control group, যা প্রসেসগুলোর রিসোর্স পরিমাপ করে) ওপর আরোপ করে। কোনো সার্ভিসে deploy.resources.limits.memory সেট করলে সেই কন্টেইনার আপনার দেওয়া সীমার বেশি মেমোরি ব্যবহার করতে পারবে না। যখনই এটি সীমা অতিক্রম করার চেষ্টা করে, kernel কন্টেইনারের ভেতরের একটি প্রসেসকে বন্ধ করে দেয় এবং কন্টেইনারটি সাধারণত 137 কোড নিয়ে বন্ধ হয়ে যায়।
VPS-এর ক্ষেত্রে এটি সবচেয়ে গুরুত্বপূর্ণ, কারণ সেখানে RAM নির্দিষ্ট থাকে এবং ধার নেওয়ার মতো কোনো অতিরিক্ত হোস্ট মেমোরি থাকে না। মেমোরি লিক বা ভুল কুয়েরি আছে এমন একটি কন্টেইনার 8GB-এর একটি বক্সে থাকা সমস্ত ফ্রি মেমোরি দখল করে নিতে পারে। তখন kernel তার বিবেচনায় সবচেয়ে ক্ষতিকর প্রসেসটিকে বন্ধ করে দেয়, যা প্রায়শই ডাটাবেস বা আপনার SSH সেশন হতে পারে, সমস্যা সৃষ্টিকারী কন্টেইনারটি নয়। এই সীমা নির্ধারণের ফলে পুরো সার্ভার ডাউন হওয়ার পরিবর্তে কেবল একটি সার্ভিস রিস্টার্ট হয়।
services:
app:
image: ghcr.io/example/app:1.4
deploy:
resources:
limits:
cpus: "1.5"
memory: 1g
reservations:
memory: 256mএটি প্রয়োগ করুন এবং সীমাটি কার্যকর হয়েছে কি না নিশ্চিত করুন:
docker compose up -d
docker stats --no-streamMEM USAGE / LIMIT কলামে 142MiB / 1GiB-এর মতো কিছু দেখা উচিত। যদি লিমিট কলামে হোস্টের সম্পূর্ণ RAM দেখায়, তবে সেটিংসটি কার্যকর হয়নি এবং এটি ঠিক না হওয়া পর্যন্ত এই গাইডের বাকি অংশ কোনো কাজে আসবে না। যদি compose ফাইলটি আপনার কাছে নতুন হয়, তবে VPS-এর জন্য Docker Compose-এর মৌলিক বিষয়সমূহ দেখুন, যা এই ফাইল লেআউটের ভিত্তি তৈরি করে।
deploy.resources.limits বনাম mem_limit: কোনটি কার্যকর
একই ধারণার জন্য দুটি ভিন্ন বানান থাকায় বিষয়টি বিভ্রান্তিকর।
mem_limit, mem_reservation, memswap_limit, cpus এবং cpu_shares হলো টপ-লেভেল সার্ভিস কি (key), যা পুরোনো Compose ফাইল ফরম্যাট থেকে এসেছে। deploy.resources এসেছে Swarm স্কিমা থেকে এবং এটি এখন Compose Specification-এর অংশ, যা docker compose বর্তমানে রিড করে।
উভয়ই একটি সিঙ্গেল হোস্টে কাজ করে। Docker Compose, যা একটি docker compose প্লাগইন, docker compose up কমান্ড চালানোর সময় deploy.resources.limits এবং deploy.resources.reservations প্রয়োগ করে, যদিও সেখানে কোনো Swarm ক্লাস্টার থাকে না। এই প্লাগইনটি এখন v5 লাইনে আছে (2026-10-10 তারিখে চেক করার সময় v5.6.0 ছিল সর্বশেষ স্টেবল রিলিজ)। পুরোনো Compose ফাইল ফরম্যাট ভার্সনের সাথে বিভ্রান্তি এড়াতে এটি v2 থেকে সরাসরি v5-এ চলে গেছে (v3 এবং v4 বাদ দেওয়া হয়েছে), এবং কোনো v5 রিলিজেই রিসোর্স লিমিট হ্যান্ডেল করার পদ্ধতিতে কোনো পরিবর্তন আনা হয়নি। deploy ব্লকের Swarm-কেন্দ্রিক অংশগুলো হলো অন্যান্য কি, যেমন placement, update_config এবং endpoint_mode, যা docker stack deploy-এর জন্য নোডগুলোর ক্লাস্টার জুড়ে শিডিউলিং এবং রোলআউট বর্ণনা করে। তাই এই সাধারণ পরামর্শটি ভুল যে "deploy-এর জন্য Swarm প্রয়োজন", এবং এটি অনুসরণ করলে আপনার সার্ভিসগুলোতে কোনো লিমিটই সেট হবে না।
প্রতিটি প্রজেক্টের জন্য যেকোনো একটি বানান বেছে নিন। একই সার্ভিসে mem_limit: 512m এবং deploy.resources.limits.memory: 1g উভয়ই লেখা কেবল পড়ার অযোগ্যই নয়, বরং Compose Specification অনুযায়ী, যখন mem_limit সেট করা থাকে তখন তা অবশ্যই limits.memory-এর সাথে সামঞ্জস্যপূর্ণ হতে হবে, এবং মানগুলো ভিন্ন হলে কোনটি কার্যকর হবে তা নির্দিষ্ট করা নেই। আপনি যে বানানই ব্যবহার করুন না কেন, ডেমনে আসলে কী প্রয়োগ করেছে তা নিশ্চিত করুন:
docker inspect --format '{{.HostConfig.Memory}} {{.HostConfig.MemoryReservation}} {{.HostConfig.NanoCpus}}' app-1মেমোরির মানগুলো বাইটে হয়, তাই 1g আউটপুট হিসেবে 1073741824 দেখায়। CPU-এর মান ন্যানো CPU-তে হয়, তাই 1.5 আউটপুট হিসেবে 1500000000 দেখায়। যেকোনো ফিল্ডে 0 থাকার অর্থ হলো কোনো লিমিট সেট করা হয়নি। Docker যে সর্বনিম্ন মেমোরি লিমিট গ্রহণ করে তা হলো 6m, এর চেয়ে কম হলে কন্টেইনারটি স্টার্ট হতে অস্বীকার করবে।
কন্টেইনার লিমিটে পৌঁছালে কী ঘটে
কন্টেইনারের গতি কমে না। এটি বন্ধ হয়ে যায়।
যখন কোনো প্রসেস মেমোরি পেজের অনুরোধ করে এবং cgroup ইতিমধ্যে তার memory.max-এ পৌঁছে যায়, তখন কার্নেল প্রথমে সেই cgroup-এর ভেতর যা সম্ভব তা পুনরুদ্ধার (reclaim) করার চেষ্টা করে: প্রথমে ক্লিন পেজ ক্যাশ, তারপর সোয়াপ করা যায় এমন পেজ। যদি এই পুনরুদ্ধারে পর্যাপ্ত মেমোরি খালি না হয়, তবে cgroup OOM (out of memory) কিলার কন্টেইনারের ভেতর থেকে একটি প্রসেস বেছে নেয় এবং সেটিকে SIGKILL পাঠায়। কন্টেইনারের PID 1-কে কিল করলে কন্টেইনারটি বন্ধ হয়ে যায়। Exit code 137 হলো মূলত 128 যোগ 9 (সিগন্যাল 9), তাই 137 যেকোনো SIGKILL-এর চিহ্ন, এটি নিজে কোনো OOM-এর প্রমাণ নয়।
docker compose ps -a
docker inspect --format '{{.State.OOMKilled}} {{.State.ExitCode}}' app-1true 137 হলো একটি OOM কিল। false 137 সাধারণত বোঝায় যে অন্য কোনো কারণে SIGKILL পাঠানো হয়েছে (একটি প্রোগ্রাম ইচ্ছাকৃতভাবেও 137 কোড দিয়ে এক্সিট করতে পারে, তবে তা বিরল), এবং এর সাধারণ কারণ হলো docker compose stop তার দশ সেকেন্ডের গ্রেস পিরিয়ড শেষ করে ফেলেছে কারণ অ্যাপটি SIGTERM উপেক্ষা করেছে। এই পার্থক্যটি বুঝতে পারলে অনেক সময় বাঁচে, কারণ সমস্যা দুটির মধ্যে কোনো মিল নেই।
আরও দুটি জায়গায় এই ঘটনা রেকর্ড করা হয়। ডেমনের লাইভ লগ দেখুন:
docker events --filter event=oomতারপর কার্নেল লগ পড়ুন, যা রিস্টার্টের পরেও টিকে থাকে:
sudo dmesg -T | grep -i -E 'memory cgroup out of memory|killed process'একটি cgroup কিল Memory cgroup out of memory: Killed process 24713 (node) দিয়ে শুরু হওয়া একটি লাইন প্রিন্ট করে। এই লাইনের অর্থ হলো একটি কন্টেইনার তার নিজস্ব লিমিটে পৌঁছেছে, এবং এটি এমন সময়ও ঘটতে পারে যখন হোস্ট মেশিনে প্রচুর RAM খালি আছে। Memory cgroup প্রিফিক্স ছাড়া কোনো লাইন মানে হলো এটি হোস্ট OOM, যার অর্থ পুরো মেশিনটিরই RAM ফুরিয়ে গেছে। লিমিট ব্যবহারের মূল উদ্দেশ্যই হলো এই ব্যর্থতা রোধ করা, তাই এটি দেখা দিলে বুঝতে হবে আপনার লিমিটগুলোর যোগফল খুব বেশি, অথবা কিছু সার্ভিসের কোনো লিমিট নেই, কিংবা Docker-এর বাইরের কোনো কিছু আপনার রাখা বাড়তি মেমোরি ব্যবহার করছে।
restart: unless-stopped-এর ক্ষেত্রে, একটি OOM লুপ সহজে ধরা পড়ে না, কারণ সার্ভিসটি মারা যাওয়ার এক সেকেন্ড পরেই docker compose ps-এ সেটিকে চালু অবস্থায় দেখায়। uptime কলাম এবং রিস্টার্ট কাউন্ট চেক করুন, এবং লিমিটের সাথে একটি হেলথচেক যা অ্যাপটিকে unhealthy হিসেবে রিপোর্ট করে যুক্ত করুন, যাতে কোনো কন্টেইনার বারবার মারা গেলে তা আপনার নজর এড়িয়ে না যায়।
Reservation একটি ইঙ্গিত মাত্র, limit-ই হলো নিয়ম
reservations.memory (পুরানো mem_reservation) হলো একটি soft floor। Docker একে এমন একটি soft limit হিসেবে বর্ণনা করে যা হোস্ট মেশিনে মেমোরির সংকট বা চাপ তৈরি হলে কার্যকর হয়। এটি কোনো কন্টেইনারকে এর চেয়ে বেশি মেমোরি ব্যবহার করা থেকে আটকায় না এবং কন্টেইনার মেমোরি চাইলে তা পাওয়ার নিশ্চয়তাও দেয় না। এটি শুধুমাত্র কার্নেলকে নির্দেশ দেয় যেন তারা প্রথমে সেই কন্টেইনারগুলোর মেমোরি রিক্লেইম (reclaim) করে, যেগুলো তাদের reservation সীমার উপরে আছে।
সুতরাং, একটি reservation নিজে থেকে কোনো কিছু সুরক্ষা দেয় না। কোনো সার্ভিসকে চাপের মুখে অগ্রাধিকার দেওয়ার জন্য এটি ব্যবহার করুন এবং নিরাপত্তার জন্য limit-এর ওপর নির্ভর করুন। Reservation-কে সবসময় limit-এর নিচে রাখুন, অন্যথায় কন্টেইনারটি স্টার্ট হবে না: Docker তখন Minimum memory limit can not be less than memory reservation limit ত্রুটি দেখিয়ে কনফিগারেশনটি প্রত্যাখ্যান করবে।
Swap accounting, সত্যি বলতে
অধিকাংশ VPS ইমেজ কোনো swap file ছাড়াই আসে। swapon --show এবং free -h কমান্ডগুলো চালান। যদি swap-এর মোট পরিমাণ শূন্য হয়, তবে নিচের swap-সংক্রান্ত কোনো সেটিংসই কাজ করবে না এবং আপনার memory limit শুধুমাত্র RAM-এর সীমাবদ্ধতা হিসেবে কাজ করবে।
memswap_limit কোনো swap-এর পরিমাণ নয়। এটি হলো memory এবং swap-এর যোগফল। mem_limit: 1g এবং memswap_limit: 2g ব্যবহার করলে, কন্টেইনারটি 1GB RAM এবং 1GB swap পাবে। দুটি মান সমান সেট করলে কন্টেইনারটি কোনো swap পাবে না। mem_limit সেট করে memswap_limit খালি রাখলে কন্টেইনারটি তার memory limit-এর সমান পরিমাণ পর্যন্ত swap ব্যবহার করতে পারবে।
Ubuntu 24.04 এবং Debian 13 ডিফল্টভাবে cgroup v2 ব্যবহার করে, যেখানে swap একটি আলাদা কাউন্টার (memory.swap.max) এবং এটি কোনো অতিরিক্ত সেটআপ ছাড়াই কাজ করে। পুরনো বার্তা Your kernel does not support swap limit capabilities মূলত cgroup v1 হোস্ট থেকে আসে যা swapaccount=1 ছাড়া বুট করা হয়েছে। সেগুলোতে memory limit কার্যকর থাকলেও swap অংশটি উপেক্ষা করা হয়।
Swap আপনার জন্য কী সুবিধা বয়ে আনে সে বিষয়ে সৎ থাকুন। এটি OOM kill-কে ধীর করে, কিন্তু সম্ভাবনা কমায় না, কারণ একটি leaking process RAM-এর মতোই swap-কেও দ্রুত পূর্ণ করে ফেলে। এদিকে, শেয়ার্ড VPS স্টোরেজে কোনো কন্টেইনার যদি swap thrashing করে, তবে তা ওই সার্ভারের অন্য সব সার্ভিসকে ধীর করে দেয়। ল্যাটেন্সি-সংবেদনশীল যেকোনো কিছুর জন্য, swap ছাড়া সঠিক limit সেট করা থাকলে তা দ্রুত এবং আরও অনুমানযোগ্যভাবে ব্যর্থ হয়।
মেমোরি ব্যবহারের পরিমাণ কেন বাস্তবে যা তার চেয়ে বেশি মনে হয়
Linux-এ, docker stats-এর MEM USAGE সংখ্যাটি শুধুমাত্র inactive page cache (cgroup v2-তে inactive_file) বিয়োগ করে, তাই সম্প্রতি ব্যবহৃত cache এখনও গণনায় থাকে। ফলে যে কন্টেইনার বড় ফাইল পড়ে, তার মেমোরি ব্যবহার সীমার কাছাকাছি পৌঁছে সেখানে স্থির হয়ে থাকে। এটি স্বাভাবিক এবং কোনো leak নয়, কারণ OOM killer সক্রিয় হওয়ার আগেই clean cache পুনরুদ্ধার করা হয়। একটি self-hosted Jellyfin media server-এর মতো সার্ভিস এই কারণেই সবসময় তার মেমোরি সীমার কাছাকাছি থাকে।
কন্টেইনারের ভেতর থেকে সংখ্যাটিকে cache এবং real working set-এ ভাগ করে দেখুন:
docker compose exec app grep -E '^(anon|file) ' /sys/fs/cgroup/memory.stat
docker compose exec app cat /sys/fs/cgroup/memory.eventsanon হলো anonymous memory, অর্থাৎ working set যা মুছে ফেলা যায় না। file হলো page cache, যা মুছে ফেলা সম্ভব। আপনার মেমোরি লিমিট নির্ধারণ করুন anon এবং কিছু অতিরিক্ত মার্জিন যোগ করে, মোট মেমোরি ব্যবহারের ওপর ভিত্তি করে নয়। memory.events ফাইলটি এই বিতর্কের চূড়ান্ত সমাধান দেয়: শূন্যের চেয়ে বেশি oom_kill কাউন্টার মানে হলো কন্টেইনারটি শুরু হওয়ার পর থেকে kernel কোনো কিছুকে kill করেছে, এবং একটি ক্রমবর্ধমান max কাউন্টার মানে হলো কন্টেইনারটিকে বর্তমানে তার সীমার মধ্যে আটকে রাখা হয়েছে। উভয় কমান্ড চালানোর জন্য ইমেজের ভেতর shell এবং coreutils থাকা প্রয়োজন, তাই distroless বা scratch ইমেজে এগুলো কাজ করবে না।
8GB VPS-এর জন্য সাইজিং লিমিট
অ্যাপ্লিকেশন থেকে নয়, বরং হোস্ট থেকে শুরু করুন। একটি 8GB VPS-এ কার্নেল, Docker daemon, sshd, journald এবং আপনার নিজের লগইন শেলের জন্য প্রায় 1GB জায়গা ছেড়ে দিন। এতে ব্যবহারের জন্য প্রায় 7GB অবশিষ্ট থাকে এবং প্রতিটি কন্টেইনারের লিমিটের যোগফল এর নিচে থাকা উচিত। ওভারকমিট করা ততক্ষণই কাজ করে, যতক্ষণ না দুটি সার্ভিস একসাথে তাদের সর্বোচ্চ রিসোর্স ব্যবহার করে।
8GB বক্সে একটি কার্যকর বিভাজন হতে পারে:
- Reverse proxy: 128m লিমিট। এটি একটি ছোট প্রসেস, এবং এই কঠোর লিমিটটি কোনো ভুল কনফিগারেশন রিলোড হলে তা দ্রুত শনাক্ত করতে সাহায্য করে।
- PostgreSQL: 2g লিমিট, যেখানে ডাটাবেস কনফিগারেশনে
shared_buffersপ্রায় 512MB সেট করা থাকে। - Application container: 1g লিমিট।
- Background worker: 512m লিমিট।
- Media বা file service: 2g লিমিট, যার বেশিরভাগই পেজ ক্যাশে হিসেবে ব্যবহৃত হবে।
এই সংখ্যাগুলো সরাসরি আপনার স্ট্যাকে কপি করবেন না। সার্ভিসগুলোকে একদিন প্রকৃত লোডের অধীনে চালান, docker stats পর্যবেক্ষণ করুন, প্রতিটি কন্টেইনারের সর্বোচ্চ anon মান নিন এবং তার সাথে আরও প্রায় অর্ধেক পরিমাণ হেডরুম হিসেবে যোগ করুন। খুব কঠোর লিমিট সেট করা লিমিট না থাকার চেয়েও খারাপ, কারণ এটি স্বাভাবিক ট্রাফিক স্পাইকের সময় একটি সচল সার্ভিসকে বন্ধ করে দিতে পারে।
একটি ফাঁদ সম্পর্কে আলাদাভাবে সতর্ক থাকা প্রয়োজন। কিছু রানটাইম লিমিটকে উপেক্ষা করে যদি না আপনি তাদের সেটি সম্পর্কে জানান, এবং যারা এটি পড়ে তারা হয়তো আপনার প্রত্যাশা অনুযায়ী নিজেদের সাইজ নির্ধারণ করে না। PostgreSQL অনায়াসেই তার shared_buffers এবং work_mem কে কন্টেইনার লিমিটের চেয়ে বড় করে ফেলে এবং তখন সেটি বন্ধ হয়ে যায়। একটি আধুনিক JVM (Java virtual machine) ডিফল্টভাবেই cgroup লিমিট শনাক্ত করতে পারে, কিন্তু OpenJDK-এর মতো HotSpot বিল্ডগুলো তখন হিপকে তার মাত্র 25 শতাংশ জায়গা দেয়। তাই হিপকে লিমিটের আরও বেশি অংশ ব্যবহার করতে দেওয়ার জন্য -XX:MaxRAMPercentage=75 ব্যবহার করা হয়, যা হিপের বাইরের মেমোরির জন্যও জায়গা রাখে। Node.js 12 নম্বর ভার্সন থেকে cgroup লিমিট অনুযায়ী তার ডিফল্ট হিপ সাইজ নির্ধারণ করে, যা কন্টেইনার লিমিটের প্রায় অর্ধেক এবং সর্বোচ্চ 2GB পর্যন্ত সীমাবদ্ধ থাকে। তাই যখন আপনি ভিন্ন কোনো সিলিং চান তখনই কেবল মেগাবাইটে --max-old-space-size সেট করুন এবং তা কন্টেইনার লিমিটের নিচে রাখুন, যাতে কার্নেল হস্তক্ষেপ করার আগেই গার্বেজ কালেক্টর কাজ করতে পারে। Ollama-এর ক্ষেত্রেও একই কথা প্রযোজ্য, তবে সেখানে ভিন্ন একটি নব (knob) ব্যবহার করতে হয়, কারণ raising num_ctx grows the KV cache করলে তা কয়েকশ মেগাবাইট বেড়ে যায় এবং দীর্ঘ প্রম্পট প্রসেস করার সময় কন্টেইনারটি বন্ধ হয়ে যায়। cgroup কোনো আলোচনা করে না। এটি সরাসরি বন্ধ করে দেয়।
CPU limit-এর আচরণ সম্পূর্ণ ভিন্ন
cpus: "1.5" মানে হলো একটি কোরের 150%, যা CFS (completely fair scheduler) কোটা হিসেবে কার্যকর করা হয়। কন্টেইনারটি প্রতি 100ms পিরিয়ডে 150ms CPU সময় পায়, যা এর সব থ্রেডের মধ্যে ভাগ করে দেওয়া হয়। এই সময় শেষ হয়ে গেলে কার্নেল এটিকে পরবর্তী পিরিয়ড পর্যন্ত অপেক্ষা করতে বাধ্য করে।
এটিই গুরুত্বপূর্ণ পার্থক্য। মেমোরি লিমিট অতিক্রম করলে একটি কন্টেইনারকে কিল (kill) করে দেওয়া হয়। কিন্তু CPU লিমিট অতিক্রম করলে কন্টেইনারটিকে থ্রটল (throttle) করা হয় এবং সেটি ধীরগতিতে চলতে থাকে। তাই CPU লিমিট কঠোরভাবে সেট করা নিরাপদ, কিন্তু মেমোরি লিমিটের ক্ষেত্রে পর্যাপ্ত জায়গা রাখা প্রয়োজন।
cpu_shares একটি ভিন্ন টুল: এটি একটি আপেক্ষিক ওয়েট (weight), যা শুধুমাত্র তখনই কার্যকর হয় যখন CPU পুরোপুরি ব্যবহৃত (saturated) থাকে। 1024 এবং 512 শেয়ারের দুটি কন্টেইনার একটি ব্যস্ত কোরকে প্রায় দুই-এক অনুপাতে ভাগ করে নেয়, আর সিস্টেম অলস থাকলে কোনোটিই সীমাবদ্ধ থাকে না। সার্ভিসের গুরুত্ব অনুযায়ী র্যাঙ্কিং করতে শেয়ার ব্যবহার করুন, আর যখন আপনার একটি নির্দিষ্ট সিলিং বা সর্বোচ্চ সীমা প্রয়োজন হয় তখন cpus ব্যবহার করুন; যেমন, রাতের বেলা চলা কোনো ট্রান্সকোড জব যেন আপনার ওয়েব সার্ভারের রিসোর্স শেষ না করে ফেলে তা নিশ্চিত করতে এটি কার্যকর।
FAQ
Docker Swarm ছাড়া কি deploy.resources.limits কাজ করে?
হ্যাঁ। Docker Compose, docker compose প্লাগইন (যা এখন v5 লাইনে আছে), একটি সিঙ্গেল হোস্টে docker compose up চালানোর সময় deploy.resources.limits এবং deploy.resources.reservations প্রয়োগ করে। এটি নিশ্চিত করতে docker inspect --format '{{.HostConfig.Memory}}' <container> ব্যবহার করুন, যা লিমিটটিকে বাইটে প্রদর্শন করে এবং কোনো লিমিট সেট করা না থাকলে 0 দেখায়। deploy-এর ভেতরে থাকা কীগুলো (keys) Swarm-এর কথা মাথায় রেখে লেখা, যেমন placement, update_config এবং endpoint_mode।
Docker Compose-এ exit code 137-এর মানে কী?
এর মানে প্রায় সবসময়ই যে মেইন প্রসেসটি SIGKILL পেয়েছে, কারণ 137 হলো 128 যোগ সিগন্যাল 9 (একটি প্রোগ্রাম ইচ্ছাকৃতভাবেও 137 দিয়ে এক্সিট করতে পারে, তবে তা বিরল)। কার্নেলের OOM killer সাধারণত এর কারণ হয়, কিন্তু অ্যাপ যদি SIGTERM উপেক্ষা করে তবে শাটডাউন টাইমআউটের ফলেও একই কোড আসতে পারে। পার্থক্য বুঝতে docker inspect --format '{{.State.OOMKilled}} {{.State.ExitCode}}' <container> চালান। true 137 হলো মেমোরি কিল, আর false 137 তা নয়।
আমার কি mem_limit নাকি deploy.resources.limits.memory সেট করা উচিত?
উভয়ই docker compose-এর সাথে কাজ করে। deploy.resources.limits.memory হলো বর্তমান Compose Specification ফরম্যাট এবং নতুন ফাইলের জন্য এটিই ভালো। যদি আপনার ফাইলের বাকি অংশ পুরনো টপ-লেভেল কী ব্যবহার করে, তবে mem_limit বজায় রাখুন। Compose Specification অনুযায়ী উভয়টি সেট করা থাকলে সেগুলোর মধ্যে সামঞ্জস্য থাকা জরুরি, তাই যেকোনো একটি বেছে নিন এবং docker inspect দিয়ে ফলাফল যাচাই করুন।
আমার কন্টেইনার কেন কিল না হয়ে মেমোরি লিমিটের সর্বোচ্চ পর্যায়ে আটকে আছে?
docker stats-এ দেখানো ব্যবহারের সংখ্যায় সাম্প্রতিক ব্যবহৃত পেজ ক্যাশও গণনা করা হয়, যা চাপের মুখে কার্নেল OOM কিল ট্রিগার না করেই মুছে ফেলে। docker compose exec <service> grep -E '^(anon|file) ' /sys/fs/cgroup/memory.stat চালান এবং anon মানটি পড়ুন, যা হলো ওয়ার্কিং সেট এবং এটি রিক্লেইম করা যায় না। একটি কম anon মানের পাশে উচ্চ file মান থাকার মানে হলো কন্টেইনারটি ডিস্ক ইনপুট এবং আউটপুট করছে, এটি মারা যাওয়ার উপক্রম হওয়া কোনো কন্টেইনার নয়।
8জিবি ভিপিএস (VPS)-এ আমার কতটুকু র্যাম বরাদ্দহীন রাখা উচিত?
কার্নেল, Docker daemon, sshd, journald এবং আপনার নিজের শেলের জন্য প্রায় 1জিবি জায়গা রাখুন, তারপর বাকি 7জিবির নিচে সমস্ত কন্টেইনার লিমিটের যোগফল রাখুন। কোনো সংখ্যা চূড়ান্ত করার আগে একদিন বাস্তব লোডের অধীনে প্রতিটি কন্টেইনারের সর্বোচ্চ anon মান পর্যবেক্ষণ করুন এবং মোট বরাদ্দকে একটি লক্ষ্যমাত্রার চেয়ে বাজেট হিসেবে বিবেচনা করুন।