SSD Nodes Learn Hosting plans →
নির্দেশিকা Matt Connorদ্বারা Matt Connor · আপডেট করা হয়েছে 2026-08-26

FreeBSD jail বনাম Docker container: কোনটি বেছে নেবেন

FreeBSD jail সম্পূর্ণ userland চালায়, আর Docker registry-এর layered image থেকে একটি process চালায়। software, state, networking ও limits-এর বাস্তব পার্থক্য জানুন।

FreeBSD jail বনাম Docker container, এক অনুচ্ছেদে

FreeBSD jail এবং Docker container একই সমস্যার সমাধান করে, তবে তাদের কাঠামো আলাদা। উভয়ই একটি অভিন্ন kernel-এর ওপর বিচ্ছিন্ন userland চালায়, তাই কোনোটিই virtual machine নয়। পার্থক্য হলো এর ভেতরে কী থাকে। Docker container একটি registry থেকে আনা layered image-এর একটি process চালায়। একটি jail সম্পূর্ণ FreeBSD userland চালায়: এর নিজস্ব /etc, নিজস্ব rc startup script, নিজস্ব pkg database থাকে এবং এতে আপনার প্রয়োজন অনুযায়ী যত process ইচ্ছা চালানো যায়। এই পৃষ্ঠার প্রায় সব অন্যান্য পার্থক্য এই একটি বিষয় থেকেই আসে।

SSD Nodes FreeBSD image দেয় না। এই platform-এ আপনি FreeBSD server ভাড়া নিতে পারবেন না, এবং নিচের কোনো অংশই এখানে কেনা যায় এমন machine-এর installation guide নয়। এটি দুটি isolation model-এর তুলনা, যাতে কোনো workload আসলে কোনটি চায় তা নির্ধারণ করতে পারেন এবং অনুমান না করে কোনো FreeBSD team's setup পড়তে পারেন।

আসলে jail কী

Jail FreeBSD 4.0-এ March 2000-এ যুক্ত হয়, তাই এটি cgroups-এর চেয়ে পুরোনো এবং Docker-এর চেয়ে প্রায় এক দশক পুরোনো। এই mechanism একটি kernel call-এর মাধ্যমে কাজ করে। jail(8) একটি directory tree নিয়ে তার ভেতরে process চালু করে এবং process-গুলোর সঙ্গে একটি jail ID যুক্ত করে। এরপর kernel ওই ID বহনকারী যেকোনো process-এর জন্য নির্দিষ্ট কিছু operation প্রত্যাখ্যান করে। কোনো jailed process তার jail-এর বাইরের process দেখতে পারে না, filesystem mount বা unmount করতে পারে না, kernel module load করতে পারে না এবং jail-কে দেওয়া হয়নি এমন network address-এ bind করতে পারে না। শেখার জন্য আলাদা namespace type নেই এবং প্রতিটি feature আলাদাভাবে opt-in করারও প্রয়োজন নেই। jail-এর configuration-এর parameter দিয়ে সামঞ্জস্য করা যায় এমন একক ব্যবস্থা হিসেবে এই restriction-গুলো কার্যকর হয়।

Host-এ jls চালালে চলমান jail-গুলোর তালিকা দেখা যায় এবং jexec web sh চালালে web নামে jail-এর ভেতরের shell-এ প্রবেশ করা যায়।

একটি directory-র মধ্যে FreeBSD userland রেখে jail তৈরি করা হয়। Base system এই কাজটি করে দেয়:

sudo bsdinstall jail /usr/local/jails/containers/web

এটি আপনার release-এর জন্য base distribution set fetch করে এবং সাধারণ post-install step চালায়। তাই নতুন server-এ যেভাবে root password সেট করেন এবং timezone নির্বাচন করেন, এখানেও ঠিক সেভাবেই করুন। ফলাফল হিসেবে একটি folder-এর মধ্যে থাকা FreeBSD installation পাওয়া যায়। এরপর /etc/jail.conf-এ সেটির বর্ণনা দিন:

web {
  host.hostname = "web.example.internal";
  path = "/usr/local/jails/containers/web";
  ip4.addr = "10.0.0.10";
  exec.start = "/bin/sh /etc/rc";
  exec.stop = "/bin/sh /etc/rc.shutdown";
  mount.devfs;
}

এটি চালু করে তারপর পরীক্ষা করুন:

sudo service jail start web
jls

এখন jls-এ একটি JID, hostname এবং IP address-সহ web তালিকাভুক্ত হওয়ার কথা। jail দেখা না গেলে সরাসরি sudo jail -c web চালান। এটি foreground-এ একই configuration প্রয়োগ করে এবং যে parameter গ্রহণ করতে পারেনি সেটি দেখায়। ফলে failure service output-এর মধ্যে চাপা পড়ে থাকে না।

দুইবার পড়ার মতো line হলো exec.start = "/bin/sh /etc/rc"। একটি jail চালু করলে তার ভেতরে FreeBSD-এর স্বাভাবিক boot script চলে। তাই jail তার নিজস্ব /etc/rc.conf-এ enabled প্রতিটি service চালু করে। Docker container-এ এর সমতুল্য কোনো ধাপ নেই, কারণ এটি image-এর entrypoint process চালায় এবং সেই process বন্ধ হলে নিজেও বন্ধ হয়ে যায়।

সফটওয়্যার কীভাবে পান: image ও registry বনাম আপনার তৈরি userland

প্রথম দিনেই আপনি এই পার্থক্যটি বুঝতে পারবেন।

Docker-এ আপনি সফটওয়্যারের নাম দেন এবং সেটি পেয়ে যান। docker pull nginx একটি layered, content-addressed image fetch করে, যা অন্য কেউ তৈরি ও পরীক্ষা করেছে। docker compose up -d এরপর volume ও network সংযুক্ত করে সেটি চালু করে। Registry-ই এখানে মূল পণ্য। Docker workflow-এর বেশিরভাগ সুবিধা হলো, হাজার হাজার project একটি কাজের image প্রকাশ করে। এ কারণেই VPS-এ Docker চালানো একটি ছোট কাজ, আলাদা project নয়।

FreeBSD কোনো default public jail image registry সরবরাহ করে না। আপনি একটি খালি userland তৈরি করেন এবং তাতে সফটওয়্যার install করেন, যেমনভাবে একটি bare server সেট up করতেন। এতে বেশি typing লাগে। তবে প্রক্রিয়াটি বেশি স্বচ্ছ, কারণ jail-এর ভিতরে যা চলে, তা pkg সেখানে install করেছে এবং host যে package set ব্যবহার করে, সেটিই ব্যবহার করেছে।

Tooling এই কাজকে সংক্ষিপ্ত করে। BastilleBSD হলো প্রচলিত jail manager, এবং এটি একটি package:

sudo pkg install bastille
sudo sysrc bastille_enable=YES
sudo bastille setup
sudo bastille bootstrap 15.1-RELEASE

bastille setup আপনার জন্য networking, storage এবং firewall configure করে। bastille bootstrap একটি release একবার download করে, এরপর তৈরি করা প্রতিটি jail সেটি পুনরায় ব্যবহার করে। FreeBSD 15.1 হলো বর্তমান production release, যা June 2026-এ প্রকাশিত হয়েছে; আপনি যে release চালান, সেটি বসান।

এরপর একটি command-এ jail তৈরি করা যায়, এবং আরেকটি command-এ তাতে software install করা যায়:

sudo bastille create web 15.1-RELEASE 10.17.89.10/24
sudo bastille pkg web install nginx
sudo bastille service web nginx start
sudo bastille console web

bastille console web jail-এর ভিতরে একটি login shell দেয়, আর bastille list host-এ কী আছে তা দেখায়। একই build পুনরাবৃত্তি করতে Bastille template ধাপগুলো একটি file-এ রাখে এবং সেগুলো jail-এ প্রয়োগ করে। এই ব্যবস্থাই Dockerfile-এর সবচেয়ে কাছাকাছি। প্রতিটি jail-এ template আবার প্রয়োগ করা হয়। কিছুই আগে থেকে built অবস্থায় আসে না।

সারসংক্ষেপটি সরল। Docker আপনাকে অন্যদের তৈরি build দেয়। Jail আপনাকে নিজের install তৈরি করতে দেয়। আপনার তালিকার সফটওয়্যার যদি শুধু container image হিসেবে প্রকাশিত হয় এবং অন্য কোনো উপায় না থাকে, তাহলে অন্য কোনো দিক বিবেচনা করার আগেই সিদ্ধান্তটি পরিষ্কার হয়ে যায়।

State এবং upgrade: ZFS যে অংশটি পরিবর্তন করে

Docker ইচ্ছাকৃতভাবে state আলাদা রাখে। Container filesystem অস্থায়ী, আপনার data named volume বা bind mount-এ থাকে, এবং upgrade হলো docker compose pull-এর পর docker compose up -d। Container প্রতিস্থাপিত হয়, আর volume-এ না রাখা সবকিছু হারিয়ে যায়। আপনি নিয়ম মেনে চললে এটি একটি সুবিধা, আর নিয়ম ভুলে গেলে data-loss incident। তাই Compose stack-এ bind mount ও named volume-এর মধ্যে নির্বাচন এত গুরুত্বপূর্ণ।

Jail state আলাদা করে না, এবং এটি সম্ভব হয় ZFS-এর কারণে। পুরো jail একটি dataset:

sudo zfs snapshot zroot/jails/containers/web@pre-upgrade
sudo pkg -j web upgrade
sudo zfs rollback zroot/jails/containers/web@pre-upgrade

এটি চালানোর আগে zfs list দিয়ে প্রকৃত dataset name পরীক্ষা করুন; উপরের path-টি handbook-এ ব্যবহৃত layout। Snapshot নিতে প্রায় এক সেকেন্ড লাগে এবং jail-এর contents পরিবর্তিত না হওয়া পর্যন্ত প্রায় কোনো অতিরিক্ত space লাগে না। Upgrade-এর কারণে service নষ্ট হলে rollback পুরো userland-কে আগের অবস্থায় ফিরিয়ে দেয়। এর মধ্যে package database এবং রাত 2am-এ হাতে সম্পাদনা করা config file-ও অন্তর্ভুক্ত। Docker-এ এর built-in সমতুল্য নেই, কারণ তার model ধরে নেয় যে আপনি কখনো এমন ব্যবস্থা চাননি।

zfs clone হলো অন্য অর্ধেক। Snapshot-এর clone হলো একটি নতুন writable jail, যা parent-এর সঙ্গে অপরিবর্তিত block ভাগ করে। তাই 3 GB jail-এর staging copy disk-এ প্রায় কোনো অতিরিক্ত space নেয় না, যতক্ষণ না আপনি এতে পরিবর্তন করা শুরু করেন। এভাবেই একজন FreeBSD admin upgrade অনুশীলনের জন্য production-এর মতো একই একটি jail তৈরি করেন।

Base system upgrade package থেকে আলাদা। যে jail-এ userland-এর নিজস্ব copy থাকে, তার জন্য:

sudo freebsd-update -b /usr/local/jails/containers/web fetch install

Thin jail এই কাজের পুনরাবৃত্তি এড়ায়। এগুলো nullfs-এর মাধ্যমে একটি shared read-only base mount করে এবং প্রতিটি jail-কে নিজস্ব একটি ছোট writable layer দেয়। তাই base একবার patch করলেই প্রতিটি jail সেই ফলাফল দেখতে পায়। Bastille ডিফল্টভাবে thin jail তৈরি করে।

Networking: প্রকাশিত port বনাম addressing সিদ্ধান্ত

Docker আপনার হয়ে networking নির্ধারণ করে এবং ব্যতিক্রমগুলো publish করতে বলে। Container-গুলো একটি bridge-এ যুক্ত হয়, user-defined network-এ service name ব্যবহার করে একে অপরের কাছে পৌঁছায়, এবং -p 8080:80 তাদের একটিকে host-এর কাছে প্রকাশ করে। এই কাজের জন্য Docker নিজস্ব packet filter rule লেখে। এ কারণেই একটি প্রকাশিত container port সরাসরি ufw অতিক্রম করে।

একটি jail শুরুতেই আপনাকে model বেছে নিতে বাধ্য করে। এর দুটি ধরন আছে।

Shared IP। ip4.addr = "10.0.0.10" বিদ্যমান host interface-এ সেই address যোগ করে এবং jail-কে সেটির মধ্যেই সীমাবদ্ধ রাখে। jail-এর নিজস্ব network stack থাকে না। তাই এটি নিজস্ব firewall চালাতে পারে না। এটি সত্যিকার অর্থে প্রতিটি address-এ bind-ও করতে পারে না। কোনো jailed socket 0.0.0.0-এর জন্য অনুরোধ করলে kernel সেটিকে jail-এর নিজস্ব address-এ পুনর্লিখন করে। একই address-এর port 80-এ দুটি jail একসঙ্গে listen করতে পারে না। তাই প্রতিটিকে আলাদা address দিতে হয়, অথবা সামনে একটি reverse proxy রাখতে হয়।

VNET। jail-এ vnet; যোগ করলে এটি একটি পূর্ণ network stack পায়: নিজস্ব interface, নিজস্ব routing table এবং নিজস্ব firewall rule। আপনি এটিকে host-এর সঙ্গে একটি epair দিয়ে সংযুক্ত করেন। এটি এমন একটি virtual cable, যার দুই প্রান্ত দুই পাশে থাকে। এরপর host প্রান্তটি একটি bridge-এ যুক্ত করেন। Docker যে networking দেয়, এর সঙ্গে এটিই সবচেয়ে বেশি মেলে। Bastille-এর -V এবং -B jail type-এর পেছনে এই mode ব্যবহৃত হয়।

Host-এর port-এ আসা traffic jail-এ পাঠানো একটি pf redirect rule। Bastille এটি সরলভাবে পরিচালনা করে:

sudo bastille rdr web tcp 80 80

এখানে কোনো EXPOSE নেই এবং স্বয়ংক্রিয় publishing-ও নেই। কোনো address বা redirect rule অনুমতি না দিলে কিছুই jail-এ পৌঁছায় না। শুরুতে এটি ধীর, তবে firewall অনেক বেশি নীরব থাকে।

রিসোর্স সীমা: cgroups বনাম rctl

Docker cgroups ব্যবহার করে একটি container-এর সীমা নির্ধারণ করে। সীমাগুলো container-এর সংজ্ঞার সঙ্গেই থাকে: কমান্ড লাইনে --memory=1g --cpus=1.5, অথবা Compose file-এ সংশ্লিষ্ট key-গুলোতে। আপনি যদি ইতিমধ্যে একটি VPS-এ Docker Compose file-এ আপনার stack সংরক্ষণ করেন, তাহলে সীমাটি যে service-এর জন্য প্রযোজ্য তার পাশেই থাকে এবং সেই service-এর সঙ্গে git-এও সংরক্ষিত হয়।

FreeBSD rctl ব্যবহার করে। এটি এমন একটি subsystem, যা আপনাকে চালু করতে হবে। প্রতিটি allocation-এ সামান্য overhead তৈরি করে বলে resource accounting ডিফল্টভাবে বন্ধ থাকে। tunable-টি /boot/loader.conf-এ যোগ করে reboot করুন:

kern.racct.enable=1

এরপর একটি rule সেট করুন এবং সেটি পর্যবেক্ষণ করুন:

sudo rctl -a jail:web:vmemoryuse:deny=1g
rctl -hu jail:web

rctl -hu jail:web jail-এর বর্তমান usage মানবপাঠ্য unit-এ দেখায়। ফলে কোনো সমস্যা হওয়ার আগে সীমার কতটা কাছাকাছি পৌঁছেছে তা বোঝা যায়। deny action jail-এর ভিতরে সীমা অতিক্রমকারী allocation ব্যর্থ করে। তাই host-এ kill message দেখার বদলে অ্যাপ্লিকেশনের নিজস্ব allocation error দেখা যায়।

rctl -a দিয়ে যোগ করা rule পরবর্তী reboot-এ মুছে যায়। FreeBSD-এর rctl service /etc/rctl.conf থেকে rule-গুলো পুনরায় load করে। তাই rule-টি ওই file-এ লিখে service-টি enable করুন:

sudo sysrc rctl_enable=YES

এই দিক থেকে Docker স্পষ্টতই বেশি সুবিধাজনক। Compose file-এ থাকা কোনো limit যে service-টির ওপর প্রয়োগ করা হয়, সেই service-এর সঙ্গেই তা review করা যায়। কিন্তু একটি rctl rule হলো আলাদা একটি file-এর একটি line, যেখানে অন্য কোথাও সংজ্ঞায়িত একটি jail-এর নাম উল্লেখ থাকে।

যখন উত্তরটি একটি virtual machine: bhyve

একটি jail host kernel শেয়ার করে। তাই কিছু কাজ তার পক্ষে স্থায়ীভাবে সম্ভব নয়। এটি অন্য kernel version চালাতে পারে না, kernel module load করতে পারে না এবং Linux container-এর মতো Linux binary চালাতে পারে না। FreeBSD-তে linuxulator নামে একটি Linux compatibility layer আছে। তবে এটি Linux system call-এর একটি subset বাস্তবায়ন করে এবং যেকোনো Linux image চালানোর সাধারণ সমাধান নয়।

bhyve হলো FreeBSD-এর hypervisor। আপনার যখন প্রকৃত machine boundary প্রয়োজন, তখন এটিই সঠিক tool। যেমন, অন্য operating system, অন্য kernel বা এমন কোনো tenant যার সঙ্গে kernel শেয়ার করতে চান না। এর বিনিময়ে shared না হয়ে reserved memory ব্যবহার করতে হয় এবং patch করার জন্য দ্বিতীয় একটি kernel বজায় রাখতে হয়। Linux-এ container ও full virtual machine-এর মধ্যে যে সিদ্ধান্ত নিতে হয়, এটি একই ধরনের সিদ্ধান্ত। এর ওপরেই নির্ভর করে আপনার নিচের স্তরে nested virtualization সমর্থনকারী একটি VPS প্রয়োজন কি না।

ইকোসিস্টেম: অধিকাংশ দল Docker বেছে নেওয়ার প্রকৃত কারণ

উপরের সব আলোচনা মডেল নিয়ে। অধিকাংশ দলের পছন্দ নির্ধারণ করে প্রতিটি মডেলের চারপাশে থাকা ইকোসিস্টেমের পরিসর।

Docker-এর সঙ্গে Docker Hub এবং GHCR, docker compose, একটি মেশিন যথেষ্ট না হলে Kubernetes, আগে থেকেই container support সংযুক্ত থাকা CI runner, এবং প্রায় প্রতিটি project-এর README-তে একটি command-এ চালানো quickstart থাকে। Jails-এর সঙ্গে থাকে FreeBSD ports tree, যা বড় এবং যত্নসহকারে রক্ষণাবেক্ষণ করা হয়, তবে প্রস্তুত অবস্থায় চালানোর মতো application bundle-এর সংখ্যা অনেক কম। কোনো project যদি শুধু container image প্রকাশ করে এবং অন্য কিছু না দেয়, FreeBSD-তে সেই সফটওয়্যার চালাতে হলে তার documentation পড়ে অংশগুলো নিজেকেই একত্র করতে হয়।

এই trade-off-এর অন্য দিকেই Jails-এর ব্যবহারিক মূল্য। আপনি এগুলো বেছে নেবেন যখন ইতিমধ্যে ZFS চালান এবং একটি সম্পূর্ণ service-এর snapshot ও rollback-কে গুরুত্ব দেন, যখন আপনার service-গুলো FreeBSD native, যখন প্রতিটি tenant-এর জন্য শুধু একটি process-এর বদলে পূর্ণ userland চান, অথবা যখন kernel, packet filter, filesystem এবং documentation-কে একটি system হিসেবে একসঙ্গে রক্ষণাবেক্ষণ করতে চান। FreeBSD-কে coherent বলা হলে সাধারণত শেষের বিষয়টিই বোঝানো হয়। server platform হিসেবে Linux ও FreeBSD-এর বিস্তৃত তুলনা এবং server ব্যবহারের জন্য FreeBSD 15-এ কী পরিবর্তন হয়েছে-এ এই বিষয়টি আরও বিস্তারিতভাবে আলোচনা করা হয়েছে।

শেষে একটি সিদ্ধান্ত। আপনার দল যদি ইতিমধ্যে Docker জানে, তাহলে স্থানান্তরের খরচ বাস্তব এবং এর সুফল নির্দিষ্ট হতে হবে। isolation quality-এর জন্য switch করবেন না; দুটি মডেল যথেষ্ট কাছাকাছি, তাই আপনার configuration-এর প্রভাব বেশি। পুরো service-এর ZFS-backed rollback চাইলে, অথবা আপনি ইতিমধ্যে FreeBSD ব্যবহার করলে switch করুন।

FAQ

আমি কি FreeBSD-তে Docker image চালাতে পারি?

Linux image নয়, এবং এটি সমর্থিত পদ্ধতিও নয়। FreeBSD-তে OCI container support আছে: sudo pkg install -y podman-suite ইনস্টল করলে Podman পাওয়া যায়, যা ocijail-এর মাধ্যমে container চালায়। এটি এমন একটি runtime, যা নিচে প্রকৃত jail তৈরি করে। Container monitor-এর জন্য fdescfs-কে /dev/fd-এ mount করতে হয় এবং container NAT (network address translation)-এর জন্য pf প্রয়োজন। FreeBSD-native OCI image সবচেয়ে ভালো কাজ করে। Linux image চালাতে অতিরিক্তভাবে Linux compatibility layer প্রয়োজন, এবং August 2026 অনুযায়ী FreeBSD Podman port-কে এখনও experimental হিসেবে বর্ণনা করা হয়। আপনার deployment যদি Linux image-এর stack হয়, তাহলে এটি Linux-এ চালান। RHEL family-তে এর অর্থ হলো Rocky Linux বা AlmaLinux-এ Docker ইনস্টল করা, যেখানে কোনো কিছু ইনস্টল করার আগেই Podman দ্বিতীয়বারের মতো এমন package হিসেবে আসে, যা ইতিমধ্যে docker command-এর মালিকানা ধরে রেখেছে।

FreeBSD jail কি Docker container-এর চেয়ে বেশি নিরাপদ?

উভয়ই একই host kernel ভাগ করে ব্যবহার করে। তাই একটি kernel bug উভয়ের জন্যই ঝুঁকি তৈরি করে, এবং প্রকৃতপক্ষে untrusted code চালানোর জন্য কোনোটিকেই আপনি boundary হিসেবে বেছে নেবেন না। পার্থক্যটি শুরু করার অবস্থায়। Jail শুরু হয় ব্যাপক পরিসরের operation নিষিদ্ধ অবস্থায়, এবং আপনি একবারে একটি parameter করে সেগুলো পুনরায় চালু করেন। Docker container শুরু হয় কিছু capability বাদ দেওয়া namespace-এর সেটের ভিতরে root হিসেবে, এবং পরবর্তী hardening স্বেচ্ছাভিত্তিক। বাস্তবে model-এর চেয়ে configuration বেশি নির্ধারণ করে: allow.mount এবং allow.raw_sockets চালু থাকা একটি jail সতর্কভাবে configured container-এর চেয়ে নিরাপদ নয়।

আমি কীভাবে একটি jail-এর backup নেব?

Dataset-এর snapshot নিন এবং সেটি পাঠান। sudo zfs snapshot zroot/jails/containers/web@backup, তারপর সেই snapshot অন্য pool-এ পাঠাতে বা box-এর বাইরে কপি করার জন্য একটি file-এ লিখতে zfs send ব্যবহার করুন। Jail তার সম্পূর্ণ userland একটি dataset-এ রাখে। তাই snapshot-এ ইনস্টল করা package, একই সময়বিন্দুতে থাকা data এবং হাতে সম্পাদনা করা প্রতিটি config file ধরা পড়ে। এটি Docker-এর প্রচলিত পদ্ধতির সম্পূর্ণ বিপরীত। সেখানে named volume এবং Compose file-এর backup নেওয়া হয়, আর বাকি অংশ image থেকে পুনর্নির্মাণ করা হয়।

আমার কি BastilleBSD প্রয়োজন, নাকি base system-ই যথেষ্ট?

Base system যথেষ্ট, এবং শুরু করার জন্য এটিই ভালো জায়গা। jail.conf, jls, jexec এবং service jail start পুরো model কভার করে। এগুলো জানার পর host-টির tooling আগে না শিখেও যেকোনো FreeBSD host পড়ে বুঝতে পারবেন। Bastille হলো এর ওপরের একটি convenience layer। এটি release bootstrap করে, thin jail তৈরি করে, template প্রয়োগ করে এবং আপনার হয়ে pf redirect rule লেখে। আগে base command শিখুন। এরপর jail-এর সংখ্যা বাড়লে হাতে কমান্ড লেখার কাজ tedious হয়ে গেলে Bastille যোগ করুন।