SSD Nodes Learn 🎉 VPS від $5.50/міс
Посібники Matt ConnorВід Matt Connor · Оновлено 2026-08-13

FreeBSD jails чи Docker: що краще для ізоляції

Порівняння FreeBSD jails і Docker: повний userland проти пошарових образів з registry, а також відмінності в стані, мережі, процесах і лімітах.

FreeBSD jails і Docker-контейнери: порівняння в одному абзаці

FreeBSD jails і Docker-контейнери вирішують одну проблему, але використовують різні підходи. Обидва запускають ізольовані userland на одному спільному ядрі, тому жоден із них не є віртуальною машиною. Відрізняється вміст ізоляції. Docker-контейнер запускає один процес із пошарового образу, завантаженого з registry. Jail запускає повний userland FreeBSD: власний /etc, власні startup-скрипти rc, власну базу даних pkg і будь-яку кількість процесів. Майже всі інші відмінності на цій сторінці випливають із цього.

SSD Nodes не пропонує образи FreeBSD. На цій платформі неможливо орендувати сервер FreeBSD, і наведений нижче матеріал не є інструкцією зі встановлення для машини, яку можна придбати тут. Це порівняння двох моделей ізоляції, підготовлене для визначення моделі, яка фактично потрібна певному навантаженню, а також для читання інструкцій із налаштування від команди FreeBSD без здогадок.

Що насправді таке jail

Jail з’явилися у FreeBSD 4.0 у березні 2000 року, тобто раніше за cgroups і приблизно на десять років раніше за Docker. Механізм використовує один виклик ядра. jail(8) бере дерево каталогів і запускає в ньому процеси з прив’язаним ідентифікатором jail, після чого ядро забороняє фіксований набір операцій будь-якому процесу з цим ідентифікатором. Процес у jail не може бачити процеси за межами свого jail, монтувати або розмонтовувати файлові системи, завантажувати модулі ядра чи прив’язуватися до мережевих адрес, які не було надано jail. Окремого типу namespace, який потрібно вивчати, немає, як і окремого ввімкнення кожного обмеження: усі обмеження застосовуються одним набором і налаштовуються параметрами в конфігурації jail.

На хості jls показує запущені jail, а jexec web sh відкриває shell усередині jail з іменем web.

Щоб створити jail, потрібно розмістити userland FreeBSD у каталозі. Базова система виконає це за вас:

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

Команда завантажує набір базової дистрибуції для вашого релізу та виконує стандартні післяінсталяційні кроки. Тому ви встановлюєте пароль root і вибираєте часовий пояс так само, як під час налаштування нового сервера. У результаті інсталяція FreeBSD міститься в каталозі. Потім опишіть її у /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;
}

Запустіть jail, а потім перевірте його стан:

sudo service jail start web
jls

Тепер jls має показати web із JID, hostname та IP-адресою. Якщо jail не відображається, безпосередньо виконайте sudo jail -c web. Команда застосовує ту саму конфігурацію у foreground і виводить параметр, який не вдалося прийняти, замість того щоб залишити інформацію про помилку лише у виводі сервісу.

Рядок, який варто перечитати двічі, — exec.start = "/bin/sh /etc/rc". Запуск jail виконує звичайний boot script FreeBSD всередині нього, тому jail запускає кожен сервіс, увімкнений у власному /etc/rc.conf. У Docker container немає еквівалентного кроку, оскільки він запускає entrypoint process образу та зупиняється, коли цей процес завершується.

Як ви отримуєте програмне забезпечення: образи та реєстри проти userland, який ви наповнюєте

Цю різницю ви відчуєте вже в перший день.

У Docker ви вказуєте програмне забезпечення й отримуєте його. docker pull nginx завантажує багатошаровий образ із адресацією за вмістом, який створив і протестував хтось інший, а docker compose up -d запускає його з підключеними томами та мережею. Реєстр є основою цього підходу. Більша частина цінності робочого процесу Docker полягає в тому, що тисячі проєктів публікують готові робочі образи. Саме тому запуск Docker на VPS займає небагато часу, а не перетворюється на окремий проєкт.

FreeBSD не постачається з типовим загальнодоступним реєстром образів jail. Ви створюєте порожній userland і встановлюєте в нього програмне забезпечення так само, як налаштовували б bare server. Це потребує більше команд. Водночас такий підхід прозоріший, оскільки в jail працює саме те, що туди встановили за допомогою pkg, з того самого набору пакетів, який використовує хост.

Інструменти скорочують цей процес. BastilleBSD — поширений менеджер jail, і він доступний як пакет:

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

bastille setup налаштовує для вас мережу, сховище та firewall. bastille bootstrap завантажує release один раз, після чого кожен створений jail повторно використовує його. FreeBSD 15.1 — поточний production release, випущений у червні 2026 року; замініть його на release, який використовуєте ви.

Після цього створення jail виконується однією командою, а його наповнення — ще однією:

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 відкриває login shell усередині jail, а bastille list показує, що є на хості. Щоб повторювати процес складання, у Bastille templates зберігають кроки у файлі та застосовують їх до jail. Це найближчий аналог Dockerfile у цьому середовищі. Template повторно застосовується до кожного jail. Нічого не надходить у готовому вигляді.

Отже, підсумок простий. Docker передає вам збірки, створені іншими. Jail дає змогу самостійно встановлювати програмне забезпечення. Якщо потрібне вам програмне забезпечення постачається лише як container image і більше ніяк, це визначає вибір ще до розгляду будь-якого іншого критерію.

Стан і оновлення: частина, яку змінює ZFS

Docker навмисно розділяє стан. Файлова система контейнера одноразова, а ваші дані зберігаються в іменованому томі або bind mount. Оновлення складається з docker compose pull, а потім docker compose up -d. Контейнер замінюється, і все, що не було розміщено в томі, втрачається. Це перевага, якщо дотримуватися правила, і втрата даних, якщо про нього забути. Саме тому вибір між bind mount і іменованими томами має таке значення в стеку Compose.

Jail не розділяє стан, і саме завдяки 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

Перед виконанням цієї команди перевірте фактичне ім’я dataset за допомогою zfs list. Наведений вище шлях відповідає структурі, яку використовує handbook. Створення snapshot займає приблизно секунду й майже не потребує додаткового місця, доки вміст jail не змінюється. Якщо після оновлення сервіс працює неправильно, rollback повертає весь userland до попереднього стану, зокрема базу даних пакетів і конфігураційні файли, які ви вручну редагували о 2:00. У Docker немає вбудованого еквівалента, оскільки його модель передбачає, що така можливість вам не потрібна.

zfs clone — друга частина. Clone snapshot — це новий доступний для запису jail, який використовує незмінені блоки спільно з батьківським dataset. Тому staging-копія jail розміром 3 GB майже не займає додаткового місця на диску, доки ви не почнете її змінювати. Так адміністратор FreeBSD створює jail, ідентичний production, щоб перевірити оновлення.

Оновлення базової системи не залежить від оновлення пакетів. Для jail, який містить власну копію userland:

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

Thin jail дає змогу не повторювати цю роботу. Він монтує одну спільну базову систему лише для читання через nullfs і надає кожному jail власний невеликий шар із доступом для запису. Тому базову систему достатньо виправити один раз, після чого зміни побачать усі jail. Bastille за замовчуванням створює thin jail.

Мережа: опубліковані порти та вибір моделі адресації

Docker самостійно визначає мережеву конфігурацію, а винятки потрібно публікувати. Контейнери підключаються до bridge-мережі, взаємодіють один з одним за іменами сервісів у user-defined network, а -p 8080:80 відкриває один із них для host. Docker створює власні правила packet filter, щоб це працювало. Саме тому опублікований порт контейнера може обійти ufw.

У jail модель потрібно вибрати заздалегідь. Є два варіанти.

Спільна IP-адреса. ip4.addr = "10.0.0.10" додає цю адресу до наявного інтерфейсу host і обмежує jail її використанням. У jail немає власного мережевого стека, тому він не може запускати власний firewall. Він також не може повноцінно прив’язатися до всіх адрес: сокет у jail, який запитує 0.0.0.0, ядро переписує на власну адресу jail. Два jail не можуть одночасно слухати порт 80 на одній адресі. Тому кожному jail призначають окрему адресу або встановлюють reverse proxy перед ними.

VNET. Додайте vnet; до jail, і він отримає повний мережевий стек: власні інтерфейси, власну таблицю маршрутизації та власні правила firewall. Підключіть його до host через epair — віртуальний кабель із одним кінцем з кожного боку — і додайте кінець host до bridge. Це найближчий аналог мережевої моделі Docker. Саме цей режим використовується для типів jail -V і -B у Bastille.

Перенаправлення порту host до jail — це правило redirect у pf. Bastille надає для нього обгортку:

sudo bastille rdr web tcp 80 80

Тут немає EXPOSE і автоматичної публікації портів. До jail не надходить трафік, якщо його адреса або правило redirect явно не дозволяє це. Запуск налаштувань займає більше часу, зате firewall працює значно тихіше.

Обмеження ресурсів: cgroups проти rctl

Docker обмежує контейнер за допомогою cgroups, а обмеження зберігаються там, де визначено контейнер: --memory=1g --cpus=1.5 у командному рядку або у відповідних ключах файлу Compose. Якщо ви вже зберігаєте свій стек у файлі Docker Compose на VPS, обмеження розташоване поруч із сервісом, якого воно стосується, і передається разом із ним у git.

У FreeBSD використовується rctl. Це підсистема, яку потрібно ввімкнути. Облік ресурсів вимкнено за замовчуванням, оскільки він додає невеликі накладні витрати під час кожного виділення. Додайте tunable до /boot/loader.conf і перезавантажте систему:

kern.racct.enable=1

Потім задайте правило та спостерігайте за ним:

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

rctl -hu jail:web виводить поточне використання ресурсів jail у зручних для читання одиницях. Так можна побачити, наскільки використання наблизилося до обмеження, перш ніж щось зламається. Дія deny призводить до помилки виділення ресурсу, що перевищує ліміт, усередині jail. Тому ви побачите власну помилку виділення застосунку, а не повідомлення про завершення процесу на хості.

Правила, додані за допомогою rctl -a, зникають після наступного перезавантаження. Сервіс rctl повторно завантажує їх із /etc/rctl.conf, тому запишіть правило до цього файлу та ввімкніть сервіс:

sudo sysrc rctl_enable=YES

Саме тут Docker помітно зручніший. Обмеження у файлі Compose перевіряється разом із сервісом, який воно обмежує. Правило rctl є рядком в окремому файлі, де вказано jail, визначений в іншому місці.

Якщо потрібна віртуальна машина: bhyve

Jail використовує ядро хоста, тому деякі можливості для нього недоступні. Він не може запускати іншу версію ядра, завантажувати модуль ядра або виконувати Linux-бінарні файли так, як це робить Linux-контейнер. У FreeBSD є рівень сумісності з Linux — linuxulator, але він реалізує лише підмножину системних викликів Linux і не є універсальним рішенням для довільних Linux-образів.

bhyve — це гіпервізор FreeBSD. Він підходить, коли потрібна реальна межа між системами: інша операційна система, інше ядро або tenant, з яким ви не хочете спільно використовувати ядро. За це доводиться платити пам’яттю, яку резервують, а не спільно використовують, і необхідністю підтримувати ще одне ядро. Це те саме рішення, яке ви приймаєте в Linux між контейнерами та повноцінними віртуальними машинами. Воно визначає, чи потрібен вам VPS із підтримкою nested virtualization під ним через VPS із підтримкою nested virtualization.

Екосистема — чесна причина, через яку більшість команд використовує Docker

Усе вище стосується моделі. Для більшості команд вибір визначає масштаб екосистеми навколо кожного варіанта.

Docker надає Docker Hub і GHCR, docker compose, Kubernetes, коли одного сервера вже недостатньо, CI runners із готовою підтримкою контейнерів і quickstart в один рядок майже в README кожного проєкту. Jails надають FreeBSD ports tree, який є великим і ретельно підтримується, а також значно менший набір готових до запуску пакетів застосунків. Якщо проєкт публікує лише container image, маршрут FreeBSD полягає в тому, щоб прочитати його документацію та самостійно зібрати всі компоненти.

Jails виправдовують себе з іншого боку цього компромісу. Обирайте їх, якщо ви вже використовуєте ZFS і цінуєте snapshot та rollback цілого сервісу, якщо ваші сервіси нативні для FreeBSD, якщо для кожного tenant потрібен повний userland замість одного процесу або якщо ви хочете, щоб kernel, packet filter, filesystem і документація підтримувалися разом як єдина система. Саме це мають на увазі, коли називають FreeBSD цілісною системою. Докладніше про це йдеться в розширеному порівнянні Linux і FreeBSD як серверних платформ і в матеріалі про зміни у FreeBSD 15 для використання на серверах.

На завершення — один висновок. Якщо ваша команда вже добре знає Docker, перехід матиме реальну ціну, а переваги мають бути конкретними. Не переходьте через якість ізоляції: ці дві моделі достатньо близькі, тому конфігурація має більше значення. Переходьте, якщо вам потрібен rollback цілих сервісів на основі ZFS або якщо ви вже використовуєте FreeBSD.

FAQ

Чи можна запускати Docker images у FreeBSD?

Не Linux images і не в режимі, який підтримується. FreeBSD має підтримку OCI containers: sudo pkg install -y podman-suite встановлює Podman, який запускає containers через ocijail — runtime, що створює звичайні jails на нижньому рівні. Для monitor контейнерів йому потрібно змонтувати fdescfs у /dev/fd, а для container NAT (network address translation) — pf. OCI images, створені для FreeBSD, працюють найкраще. Для Linux images додатково потрібен Linux compatibility layer, а станом на August 2026 порт FreeBSD Podman усе ще описується як експериментальний. Якщо ваше розгортання складається зі stack Linux images, запускайте його в Linux.

Чи безпечніші FreeBSD jails за Docker containers?

Обидва типи ізоляції використовують одне ядро хоста, тому помилка в ядрі становить ризик для обох. Жоден із них не є межею ізоляції, яку варто обирати для справді ненадійного коду. Відмінність полягає у вихідних налаштуваннях. Jail починається з широкого набору заборонених операцій, а потім ви вмикаєте їх по одному параметру. Docker container починається як root у наборі namespaces із вимкненими деякими capabilities, а додаткове посилення безпеки потрібно вмикати окремо. На практиці рівень безпеки більше залежить від конфігурації, ніж від моделі: jail із увімкненими allow.mount і allow.raw_sockets не є безпечнішим за ретельно налаштований container.

Як створити резервну копію jail?

Створіть snapshot dataset і передайте його. sudo zfs snapshot zroot/jails/containers/web@backup, а потім zfs send цей snapshot до іншого pool або у файл, який ви скопіюєте за межі сервера. Оскільки jail зберігає весь свій userland в одному dataset, snapshot містить встановлені пакети та дані в одному узгодженому стані, а також усі config files, які ви редагували вручну. Це протилежність підходу Docker, за якого ви створюєте резервні копії named volumes і Compose file, а решту відновлюєте з image.

Чи потрібен BastilleBSD, чи достатньо base system?

Base system достатньо, і саме з нього краще почати. jail.conf, jls, jexec і service jail start охоплюють усю модель. Знаючи їх, ви зможете працювати з будь-яким FreeBSD host, не вивчаючи спочатку його tooling. Bastille — це convenience layer над базовою системою: він завантажує releases, створює thin jails, застосовує templates і додає для вас pf redirect rules. Спочатку вивчіть базові команди, а потім додайте Bastille, коли кількість jails зробить ручне введення команд незручним.