FreeBSD jails और Docker containers में मुख्य अंतर क्या हैं
FreeBSD jails और Docker containers के बीच तकनीकी अंतर समझें। Jails एक पूर्ण userland चलाती हैं जबकि Docker layered images का उपयोग करता है। इनके networking और limits की तुलना देखें।
FreeBSD jails और Docker containers एक ही समस्या को दो अलग-अलग रूपों में हल करते हैं। दोनों एक साझा kernel पर isolated userlands चलाते हैं, इसलिए इनमें से कोई भी virtual machine नहीं है। अंतर केवल इस बात का है कि इनके भीतर क्या होता है। एक Docker container किसी registry से pull की गई layered image से एक process चलाता है। एक jail एक पूर्ण FreeBSD userland चलाती है: अपना स्वयं का /etc, अपनी rc startup scripts, अपना स्वयं का pkg database, और जितनी चाहें उतनी processes। इस पृष्ठ पर मौजूद लगभग सभी अन्य अंतर इसी एक मुख्य अंतर से उत्पन्न होते हैं।
SSD Nodes FreeBSD images प्रदान नहीं करता है। आप इस platform पर FreeBSD server किराए पर नहीं ले सकते, और नीचे दी गई जानकारी आपके द्वारा यहाँ खरीदी जा सकने वाली किसी मशीन के लिए install guide नहीं है। यह दो isolation models की तुलना है, जिसे इसलिए लिखा गया है ताकि आप यह समझ सकें कि किसी workload को वास्तव में किसकी आवश्यकता है, और ताकि आप FreeBSD टीम के setup को बिना किसी अनुमान के पढ़ सकें।
Jail वास्तव में क्या है
Jails को FreeBSD 4.0 में मार्च 2000 में पेश किया गया था, जो इन्हें cgroups से पुराना और Docker से लगभग एक दशक पुराना बनाता है। यह तंत्र एक kernel call है। jail(8) एक directory tree लेता है और उसके अंदर एक jail ID के साथ processes शुरू करता है, और फिर kernel उस ID वाली किसी भी process के लिए निश्चित ऑपरेशन्स को अस्वीकार कर देता है। एक jailed process अपनी jail के बाहर की processes को नहीं देख सकती, filesystems को mount या unmount नहीं कर सकती, kernel modules लोड नहीं कर सकती, और उन network addresses से bind नहीं हो सकती जो jail को नहीं दिए गए हैं। इसमें सीखने के लिए कोई अलग namespace प्रकार नहीं है और न ही प्रति-सुविधा (per-feature) कोई opt-in है: ये प्रतिबंध एक इकाई के रूप में आते हैं, जिन्हें jail के config में parameters द्वारा समायोजित किया जाता है।
Host पर, jls चल रही jails की सूची दिखाता है और 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 steps चलाता है, ताकि आप 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;
}इसे start करें, फिर इसे check करें:
sudo service jail start web
jlsjls को अब JID, hostname और IP address के साथ web को सूचीबद्ध करना चाहिए। यदि jail दिखाई नहीं देती है, तो सीधे sudo jail -c web चलाएँ। यह foreground में वही configuration लागू करता है और उस parameter को print करता है जिसे वह स्वीकार नहीं कर सका, बजाय इसके कि विफलता को service output में छोड़ दे।
जो पंक्ति दो बार पढ़ने योग्य है वह exec.start = "/bin/sh /etc/rc" है। एक jail को start करने पर उसके अंदर FreeBSD की सामान्य boot script चलती है, इसलिए jail अपने स्वयं के /etc/rc.conf में सक्षम (enabled) हर service को शुरू कर देती है। Docker container में इसका कोई समकक्ष चरण नहीं है, क्योंकि यह image की entrypoint process को चलाता है और उस process के रुकने पर खुद रुक जाता है।
सॉफ्टवेयर प्राप्त करने के तरीके: images और registries बनाम userland जिसे आप स्वयं भरते हैं
यह वह अंतर है जिसे आप पहले दिन ही महसूस करते हैं।
Docker के साथ आप सॉफ्टवेयर का नाम लेते हैं और उसे प्राप्त कर लेते हैं। docker pull nginx एक layered, content-addressed image को fetch करता है जिसे किसी और ने बनाया और टेस्ट किया है, और docker compose up -d इसे इसके volumes और network के साथ start कर देता है। registry ही वह उत्पाद है। Docker workflow का अधिकांश मूल्य इस तथ्य में है कि हजारों प्रोजेक्ट्स एक working image प्रकाशित करते हैं, जो VPS पर Docker चलाने को एक लंबा प्रोजेक्ट बनाने के बजाय एक छोटा सा काम बना देता है।
FreeBSD jail images की कोई डिफ़ॉल्ट public registry प्रदान नहीं करता है। आप एक खाली userland बनाते हैं और उसमें इंस्टॉलेशन करते हैं, ठीक वैसे ही जैसे आप एक bare server को सेटअप करते हैं। इसमें टाइपिंग अधिक होती है। यह अधिक पारदर्शी भी है, क्योंकि jail में वही चलता है जो pkg ने वहां रखा है, उसी package set से जिसका उपयोग host करता है।
Tooling इसे संक्षिप्त बनाती है। BastilleBSD एक सामान्य jail manager है और यह एक package है:
sudo pkg install bastille
sudo sysrc bastille_enable=YES
sudo bastille setup
sudo bastille bootstrap 15.1-RELEASEbastille setup आपके लिए networking, storage और firewall को configure करता है। bastille bootstrap एक release को एक बार डाउनलोड करता है, और उसके बाद आपके द्वारा बनाई गई हर jail उसका पुन: उपयोग करती है। FreeBSD 15.1 वर्तमान production release है, जो जून 2026 में जारी हुआ है; आप जो भी release चला रहे हैं उसे यहाँ लिखें।
Jail बनाना एक command का काम है, और उसे भरना एक और command का:
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 webbastille console web आपको jail के अंदर एक login shell देता है, और bastille list दिखाता है कि host पर क्या मौजूद है। किसी build को दोहराने के लिए, Bastille templates चरणों को एक file में रखते हैं और उन्हें jail पर लागू करते हैं, जो इस दुनिया में Dockerfile के सबसे करीब है। एक template को हर jail पर फिर से चलाया जाता है। कुछ भी prebuilt नहीं आता है।
इसलिए ईमानदार सारांश संक्षिप्त है। Docker आपको दूसरों के builds देता है। Jails आपको अपने स्वयं के installs देती हैं। यदि आपकी shortlist का सॉफ्टवेयर केवल container image के रूप में उपलब्ध है और किसी अन्य रूप में नहीं, तो यह किसी अन्य तर्क से पहले ही निर्णय तय कर देता है।
State और अपग्रेड: ZFS द्वारा बदलाव
Docker जानबूझकर state को अलग रखता है। container का filesystem अस्थायी होता है, आपका डेटा एक named volume या bind mount में रहता है, और अपग्रेड का मतलब docker compose pull के बाद docker compose up -d करना होता है। container बदल दिया जाता है, और जो कुछ भी आपने volume में नहीं रखा था, वह नष्ट हो जाता है। यदि आप नियमों का पालन करते हैं तो यह एक फीचर है, और यदि आप भूल जाते हैं तो यह डेटा हानि की घटना है, यही कारण है कि bind mounts और named volumes के बीच का चुनाव एक Compose stack में बहुत महत्वपूर्ण होता है।
एक 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 नाम की जाँच करें; ऊपर दिया गया path वह layout है जिसका handbook उपयोग करता है। snapshot में लगभग एक सेकंड का समय लगता है और जब तक jail की सामग्री नहीं बदलती, तब तक यह लगभग कोई जगह नहीं घेरता है। यदि अपग्रेड service को खराब कर देता है, तो rollback पूरे userland को उसकी पिछली स्थिति में लौटा देता है, जिसमें package database और वे config files भी शामिल हैं जिन्हें आपने रात के 2 बजे हाथ से edit किया था। Docker में इसका कोई इन-बिल्ट विकल्प नहीं है, क्योंकि इसका मॉडल यह मानकर चलता है कि आपको इसकी कभी आवश्यकता नहीं होगी।
zfs clone इसका दूसरा हिस्सा है। एक snapshot का clone एक नई writable jail होती है जो अपने parent के साथ अपरिवर्तित blocks साझा करती है, इसलिए 3 GB की jail की एक staging copy डिस्क पर लगभग कुछ भी खर्च नहीं करती जब तक कि आप उसे बदलना शुरू न करें। इसी तरह एक FreeBSD admin अपग्रेड का पूर्वाभ्यास करने के लिए "production के समान" jail बनाता है।
Base system का अपग्रेड packages से अलग होता है। userland की अपनी copy रखने वाली jail के लिए:
sudo freebsd-update -b /usr/local/jails/containers/web fetch installThin jails उस काम को दोहराने से बचती हैं। वे nullfs के माध्यम से एक साझा read-only base को mount करती हैं और प्रत्येक jail को अपनी एक छोटी writable layer देती हैं, इसलिए आप base को एक बार patch करते हैं और हर jail को परिणाम दिखाई देता है। Bastille डिफ़ॉल्ट रूप से thin jails बनाता है।
नेटवर्किंग: पब्लिश किए गए पोर्ट बनाम एड्रेसिंग का निर्णय
Docker आपके लिए नेटवर्किंग का निर्णय लेता है और आपसे अपवादों (exceptions) को पब्लिश करने के लिए कहता है। कंटेनर एक ब्रिज पर स्थित होते हैं, वे user-defined नेटवर्क पर सर्विस नाम के माध्यम से एक-दूसरे तक पहुँचते हैं, और -p 8080:80 उनमें से किसी एक को होस्ट के लिए expose करता है। इसे संभव बनाने के लिए Docker अपने स्वयं के पैकेट फिल्टर नियम लिखता है, और यही कारण है कि एक पब्लिश किया गया कंटेनर पोर्ट सीधे ufw को बायपास कर देता है।
एक जेल (jail) आपको शुरुआत में ही मॉडल चुनने के लिए मजबूर करती है, और इसके दो प्रकार हैं।
Shared IP. ip4.addr = "10.0.0.10" उस एड्रेस को मौजूदा होस्ट इंटरफेस में जोड़ता है और जेल को उसी तक सीमित कर देता है। जेल का अपना कोई नेटवर्क स्टैक नहीं होता, इसलिए यह अपना खुद का फायरवॉल नहीं चला सकती। यह वास्तव में हर एड्रेस पर बाइंड भी नहीं हो सकती: 0.0.0.0 के लिए अनुरोध करने वाले एक jailed सॉकेट को कर्नल द्वारा जेल के अपने एड्रेस पर फिर से लिखा (rewrite) जाता है। दो जेलें एक ही एड्रेस के पोर्ट 80 पर एक साथ लिसन नहीं कर सकतीं, इसलिए आप प्रत्येक को एक एड्रेस देते हैं, या आप सामने एक रिवर्स प्रॉक्सी लगा देते हैं।
VNET. जेल में vnet; जोड़ें और इसे एक पूर्ण नेटवर्क स्टैक मिल जाता है: इसके अपने इंटरफेस, अपनी राउटिंग टेबल, और अपने फायरवॉल नियम। आप इसे एक epair के साथ होस्ट से जोड़ते हैं, जो एक वर्चुअल केबल है जिसका एक सिरा दोनों तरफ होता है, और होस्ट वाले सिरे को एक ब्रिज पर रखते हैं। यह Docker द्वारा प्रदान की जाने वाली सुविधा के सबसे करीब है, और यही वह मोड है जो Bastille के -V और -B जेल प्रकारों के पीछे काम करता है।
होस्ट पोर्ट को जेल में फॉरवर्ड करना एक pf रीडायरेक्ट नियम है। Bastille इसे इस प्रकार रैप करता है:
sudo bastille rdr web tcp 80 80इसमें कोई EXPOSE नहीं होता और न ही कोई स्वचालित पब्लिशिंग होती है। जेल तक कुछ भी तब तक नहीं पहुँचता जब तक कि उसका एड्रेस या रीडायरेक्ट नियम इसकी अनुमति न दे। यह एक धीमी शुरुआत है और एक बहुत ही शांत फायरवॉल है।
संसाधन सीमाएँ: cgroups बनाम rctl
Docker एक container को cgroups के साथ सीमित करता है, और ये सीमाएँ वहीं रहती हैं जहाँ container परिभाषित होता है: command line पर --memory=1g --cpus=1.5, या Compose file में संबंधित keys। यदि आप अपना stack पहले से ही a Docker Compose file on a VPS में रखते हैं, तो सीमा उस service के साथ रहती है जिस पर वह लागू होती है और git में उसके साथ ही चलती है।
FreeBSD rctl का उपयोग करता है, और यह एक ऐसा subsystem है जिसे आपको चालू करना पड़ता है। Resource accounting डिफ़ॉल्ट रूप से बंद रहता है क्योंकि यह हर allocation पर थोड़ी लागत लेता है। /boot/loader.conf में tunable जोड़ें और reboot करें:
kern.racct.enable=1फिर एक rule सेट करें और उसे monitor करें:
sudo rctl -a jail:web:vmemoryuse:deny=1g
rctl -hu jail:webrctl -hu jail:web jail के वर्तमान उपयोग को human-readable units में print करता है, ताकि आप देख सकें कि किसी भी चीज़ के टूटने से पहले यह सीमा के कितना करीब है। deny action jail के अंदर over-limit allocation को विफल कर देता है, ताकि आप host पर kill message के बजाय application का अपना allocation error देख सकें।
rctl -a के साथ जोड़े गए rules अगले reboot पर गायब हो जाते हैं। FreeBSD की rctl service उन्हें /etc/rctl.conf से reload करती है, इसलिए rule को उस file में लिखें और service को enable करें:
sudo sysrc rctl_enable=YESयह वह बिंदु है जहाँ Docker स्पष्ट रूप से अधिक सुविधाजनक है। Compose file में एक सीमा की समीक्षा उस service के साथ की जाती है जिसे वह नियंत्रित करती है। एक rctl rule एक अलग file में लिखी गई एक पंक्ति है जो कहीं और परिभाषित jail का नाम लेती है।
जब उत्तर एक virtual machine हो: bhyve
Jail होस्ट kernel को साझा करती है, इसलिए कुछ चीजें हमेशा पहुंच से बाहर रहती हैं। यह एक अलग kernel version नहीं चला सकती, यह kernel module लोड नहीं कर सकती, और यह Linux binaries को उस तरह नहीं चला सकती जैसे Linux container चलाते हैं। FreeBSD में एक Linux compatibility layer है, जिसे linuxulator कहते हैं, लेकिन यह Linux system calls के केवल एक subset को लागू करता है और यह मनमाने Linux images के लिए कोई सामान्य समाधान नहीं है।
bhyve, FreeBSD का hypervisor है, और जब आपको एक वास्तविक machine boundary की आवश्यकता हो, तो यह सही उपकरण है: एक अलग operating system, एक अलग kernel, या ऐसा tenant जिसके साथ आप kernel साझा नहीं करना चाहते। इसकी कीमत आपको उस memory के रूप में चुकानी पड़ती है जो साझा होने के बजाय आरक्षित (reserved) होती है, और एक दूसरे kernel को patch करने के रूप में चुकानी पड़ती है। यह वही निर्णय है जो आप Linux पर containers और full virtual machines के बीच लेते हैं, और यही वह निर्णय है जो यह तय करता है कि आपको नीचे nested virtualization का समर्थन करने वाला VPS चाहिए या नहीं।
इकोसिस्टम, जो कि अधिकांश टीमों द्वारा Docker उपयोग करने का वास्तविक कारण है
ऊपर दी गई हर बात मॉडल के बारे में है। अधिकांश टीमों के लिए चुनाव का आधार यह है कि प्रत्येक के आसपास की दुनिया कितनी बड़ी है।
Docker अपने साथ Docker Hub और GHCR, docker compose, Kubernetes (जब एक सर्वर पर्याप्त न रहे), पहले से कॉन्फ़िगर किए गए कंटेनर सपोर्ट वाले CI रनर्स, और लगभग हर प्रोजेक्ट की README में एक-कमांड क्विकस्टार्ट लाता है। Jails अपने साथ FreeBSD पोर्ट्स ट्री लाते हैं, जो विशाल है और सावधानीपूर्वक मेंटेन किया जाता है, साथ ही इसमें उपयोग के लिए तैयार एप्लिकेशन बंडल्स का एक छोटा सेट भी होता है। जब कोई प्रोजेक्ट केवल एक कंटेनर इमेज पब्लिश करता है, तो FreeBSD का तरीका यह है कि आप उसके डॉक्यूमेंटेशन को पढ़ें और स्वयं पुर्जों को असेंबल करें।
Jails इस समझौते के दूसरी ओर अपना स्थान बनाते हैं। आप उन्हें तब चुनते हैं जब आप पहले से ZFS चला रहे हों और पूरी सर्विस के स्नैपशॉट और रोलबैक को महत्व देते हों, जब आपकी सर्विसेज FreeBSD नेटिव हों, जब आप एक सिंगल प्रोसेस के बजाय प्रति टेनेंट एक पूर्ण यूजरलैंड चाहते हों, या जब आप चाहते हों कि कर्नल, पैकेट फिल्टर, फाइलसिस्टम और डॉक्यूमेंटेशन एक सिस्टम के रूप में एक साथ मेंटेन किए जाएं। अंतिम बिंदु का अर्थ वही है जिसे लोग FreeBSD को 'सुसंगत' (coherent) कहते समय संदर्भित करते हैं, और इस पर सर्वर प्लेटफॉर्म के रूप में Linux और FreeBSD की व्यापक तुलना और FreeBSD 15 ने सर्वर उपयोग के लिए क्या बदलाव किए में अधिक विस्तार से चर्चा की गई है।
एक अंतिम निष्कर्ष। यदि आपकी टीम पहले से Docker जानती है, तो स्विच करने की लागत वास्तविक है और इसका लाभ विशिष्ट होना चाहिए। केवल आइसोलेशन क्वालिटी के लिए स्विच न करें; दोनों मॉडल इतने करीब हैं कि आपका कॉन्फ़िगरेशन अधिक मायने रखता है। स्विच तब करें जब आप पूरी सर्विसेज के ZFS-आधारित रोलबैक चाहते हों, या जब आप पहले से ही FreeBSD पर हों।
FAQ
क्या मैं FreeBSD पर Docker images चला सकता हूँ?
Linux images नहीं, और न ही यह एक समर्थित तरीका है। FreeBSD में OCI container का समर्थन मौजूद है: sudo pkg install -y podman-suite, Podman को install करता है, जो ocijail के माध्यम से containers चलाता है। यह एक runtime है जो वास्तव में jails बनाता है। इसके लिए container monitor हेतु fdescfs को /dev/fd पर mount करना आवश्यक है, और container NAT (network address translation) के लिए pf की आवश्यकता होती है। FreeBSD-native OCI images सबसे बेहतर काम करती हैं। Linux images के लिए अतिरिक्त रूप से Linux compatibility layer की आवश्यकता होती है, और अगस्त 2026 तक FreeBSD Podman port को अभी भी experimental माना जाता है। यदि आपका deployment Linux images का एक stack है, तो इसे Linux पर ही चलाएं।
क्या FreeBSD jails, Docker containers से अधिक सुरक्षित हैं?
दोनों एक ही host kernel साझा करते हैं, इसलिए kernel bug दोनों के लिए जोखिम है, और आप किसी भी तकनीक को पूरी तरह से अविश्वसनीय (untrusted) code के लिए boundary के रूप में नहीं चुनेंगे। अंतर शुरुआत के तरीके में है। एक jail की शुरुआत इस तरह होती है कि अधिकांश operations को मना कर दिया जाता है और आप उन्हें एक-एक parameter करके enable करते हैं। एक Docker container की शुरुआत namespaces के भीतर root के रूप में होती है, जिसमें कुछ capabilities को हटा दिया जाता है, और आगे की hardening आपकी इच्छा पर निर्भर करती है। व्यवहार में, configuration मॉडल से अधिक मायने रखती है: यदि कोई jail allow.mount और allow.raw_sockets के साथ चल रही है, तो वह सावधानीपूर्वक configure किए गए container से अधिक सुरक्षित नहीं है।
मैं jail का backup कैसे लूँ?
Dataset का snapshot लें और उसे भेजें। sudo zfs snapshot zroot/jails/containers/web@backup का उपयोग करें, फिर उस snapshot को zfs send करके किसी अन्य pool में या ऐसी file में भेजें जिसे आप box से बाहर copy कर सकें। चूंकि एक jail अपना पूरा userland एक ही dataset में रखती है, इसलिए snapshot installed packages और data को एक consistent point पर capture कर लेता है, साथ ही उन सभी config files को भी जिन्हें आपने manually edit किया है। यह Docker की आदत के विपरीत है, जहाँ आप named volumes और Compose file का backup लेते हैं और बाकी सब कुछ image से फिर से बनाते हैं।
क्या मुझे BastilleBSD की आवश्यकता है, या base system पर्याप्त है?
Base system पर्याप्त है, और शुरुआत करने के लिए यह बेहतर जगह है। jail.conf, jls, jexec और service jail start पूरे मॉडल को कवर करते हैं, और एक बार जब आप इन्हें जान लेते हैं, तो आप किसी भी FreeBSD host को बिना उस host के विशिष्ट tooling को सीखे समझ सकते हैं। Bastille इसके ऊपर एक सुविधा परत (convenience layer) है: यह releases को bootstrap करती है, thin jails बनाती है, templates लागू करती है और आपके लिए pf redirect rules लिखती है। पहले base commands सीखें, फिर जब jails की संख्या अधिक होने के कारण typing बोझिल लगने लगे, तब Bastille का उपयोग करें।