SSD Nodes Learn Hosting plans →
Руководства Matt ConnorАвтор: Matt Connor · Обновлено 2026-08-25

FreeBSD jails или Docker: сравнение технологий изоляции

Узнайте ключевые различия между FreeBSD jails и Docker containers. Мы разбираем архитектуру, управление состоянием, работу с сетью и ограничения для выбора оптимальной модели.

Сравнение FreeBSD jails и Docker containers в одном абзаце

FreeBSD jails и Docker containers решают одну и ту же задачу, но разными способами. Оба решения запускают изолированные пользовательские окружения на одном общем ядре, поэтому ни одно из них не является виртуальной машиной. Разница заключается в содержимом. Docker container запускает один процесс из слоистого образа, загруженного из реестра. Jail запускает полноценное пользовательское окружение FreeBSD: собственную /etc, свои скрипты автозагрузки rc, свою базу данных pkg и любое количество процессов. Почти все остальные различия, описанные на этой странице, вытекают из этого фундаментального отличия.

SSD Nodes не предоставляет образы FreeBSD. Вы не можете арендовать сервер с FreeBSD на этой платформе, и нижеприведенный текст не является руководством по установке для оборудования, которое можно здесь приобрести. Это сравнение двух моделей изоляции, написанное для того, чтобы вы могли определить, какая из них подходит для конкретной рабочей нагрузки, и чтобы вы могли понять конфигурацию команды FreeBSD без догадок.

What a jail actually is

Jails arrived in FreeBSD 4.0 in March 2000, which makes them older than cgroups and roughly a decade older than Docker. The mechanism is one kernel call. jail(8) takes a directory tree and starts processes inside it with a jail ID attached, and the kernel then refuses a fixed set of operations for any process carrying that ID. A jailed process cannot see processes outside its jail, cannot mount or unmount filesystems, cannot load kernel modules, and cannot bind to network addresses the jail was not given. There is no separate namespace type to learn and no per-feature opt-in: the restrictions arrive as one unit, adjusted by parameters in the jail's config.

On the host, jls lists running jails and jexec web sh drops you into a shell inside the one named web.

You build a jail by putting a FreeBSD userland into a directory. The base system does that for you:

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

That fetches the base distribution set for your release and runs the ordinary post-install steps, so you set a root password and pick a timezone exactly as you would on a new server. The result is a FreeBSD installation sitting in a folder. You then describe it in /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 it, then check it:

sudo service jail start web
jls

jls should now list web with a JID, its hostname and its IP address. If the jail does not appear, run sudo jail -c web directly. It applies the same configuration in the foreground and prints the parameter it could not accept, instead of leaving the failure in the service output.

The line worth reading twice is exec.start = "/bin/sh /etc/rc". Starting a jail runs FreeBSD's normal boot script inside it, so the jail brings up every service enabled in its own /etc/rc.conf. A Docker container has no equivalent step, because it runs the image's entrypoint process and stops when that process stops.

Способы доставки ПО: образы и реестры против самостоятельного наполнения окружения

Это разница, которую вы почувствуете в первый же день.

В Docker вы указываете имя программы и получаете её. docker pull nginx загружает послойный образ с адресацией по содержимому, который кто-то другой собрал и протестировал, а docker compose up -d запускает его с подключенными томами и сетью. Реестр — это и есть продукт. Основная ценность рабочего процесса Docker заключается в том, что тысячи проектов публикуют готовые к работе образы, что делает запуск Docker на VPS быстрой задачей, а не полноценным проектом.

FreeBSD не предоставляет публичного реестра образов jail по умолчанию. Вы создаете пустое пользовательское окружение и устанавливаете в него ПО так же, как настраивали бы обычный сервер. Это требует больше ввода команд. Но это также прозрачнее, так как в jail работает именно то, что поместил туда pkg, используя тот же набор пакетов, что и хостовая система.

Инструменты позволяют ускорить процесс. BastilleBSD — популярный менеджер jail, доступный в виде пакета:

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

bastille setup настраивает за вас сеть, хранилище и межсетевой экран. bastille bootstrap загружает релиз один раз, и каждый последующий jail использует его повторно. FreeBSD 15.1 — текущий производственный релиз, вышедший в июне 2026 года; подставьте версию, которую используете вы.

Создание 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 предоставляет оболочку для входа в jail, а bastille list показывает, что существует на хосте. Чтобы повторить сборку, шаблоны Bastille сохраняют шаги в файле и применяют их к jail; это максимально близкий аналог Dockerfile в данном мире. Шаблон воспроизводится для каждого jail. Ничего не приходит в готовом виде.

Краткий итог: Docker предоставляет вам чужие сборки. Jails предоставляют вам возможность выполнить установку самостоятельно. Если ПО из вашего списка поставляется только в виде контейнерного образа, это решает вопрос до рассмотрения любых других критериев.

Состояние и обновления: особенности ZFS

Docker намеренно разделяет состояние. Файловая система контейнера является временной, данные хранятся в именованном томе или bind mount, а обновление выполняется через docker compose pull с последующим docker compose up -d. Контейнер заменяется, и всё, что не было сохранено в томе, удаляется. Это преимущество, если вы следуете правилам, и причина потери данных, если вы о них забыли. Именно поэтому выбор между bind mounts и именованными томами имеет такое большое значение в стеке 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; указанный выше путь соответствует структуре из руководства. Создание снимка занимает около секунды и почти не требует места, пока содержимое jail не изменится. Если обновление нарушает работу сервиса, откат возвращает всё пользовательское окружение в исходное состояние, включая базу данных пакетов и конфигурационные файлы, которые вы правили вручную в 2 часа ночи. В Docker нет встроенного аналога, так как его модель предполагает, что вам это никогда не потребуется.

zfs clone — это вторая часть процесса. Клон снимка — это новый jail с возможностью записи, который использует общие блоки с родительским объектом. Поэтому создание тестовой копии jail объёмом 3 ГБ почти не занимает места на диске, пока вы не начнёте вносить изменения. Именно так администратор FreeBSD создает копию jail, идентичную рабочей, для отработки обновления.

Обновление базовой системы выполняется отдельно от пакетов. Для jail, содержащего собственную копию пользовательского окружения:

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

Тонкие (thin) jails позволяют избежать повторения этой работы. Они монтируют общую базовую систему в режиме «только чтение» через nullfs и предоставляют каждому jail небольшой слой с возможностью записи. Таким образом, вы обновляете базу один раз, и все jails сразу видят результат. Bastille создает тонкие jails по умолчанию.

Сети: опубликованные порты против выбора адресации

Docker самостоятельно управляет сетью и запрашивает публикацию исключений. Контейнеры попадают в мост, взаимодействуют друг с другом по имени сервиса в пользовательской сети, а -p 8080:80 открывает один из них для хоста. Для этого Docker записывает собственные правила фильтрации пакетов; именно так опубликованный порт контейнера обходит ufw.

Jail требует выбора модели на начальном этапе, и их существует две.

Shared IP. ip4.addr = "10.0.0.10" добавляет этот адрес к существующему интерфейсу хоста и ограничивает jail этим адресом. У jail нет собственного сетевого стека, поэтому он не может запускать собственный межсетевой экран. Он также не может полноценно привязываться ко всем адресам: сокет внутри jail, запрашивающий 0.0.0.0, переписывается ядром на собственный адрес jail. Два jail не могут одновременно слушать порт 80 на одном и том же адресе, поэтому вы назначаете каждому свой адрес или устанавливаете перед ними reverse proxy.

VNET. Добавьте vnet; в jail, и он получит полноценный сетевой стек: собственные интерфейсы, собственную таблицу маршрутизации, собственные правила межсетевого экрана. Вы соединяете его с хостом через epair — виртуальный кабель, концы которого находятся с обеих сторон, — и помещаете конец со стороны хоста в мост. Это максимально близкий аналог того, что предоставляет Docker, и именно этот режим лежит в основе типов jail -V и -B в Bastille.

Перенаправление порта хоста в jail — это правило перенаправления pf. Bastille выполняет его обертку:

sudo bastille rdr web tcp 80 80

Здесь нет EXPOSE и автоматической публикации. Ничто не достигнет jail, пока его адрес или правило перенаправления не разрешат это. Это более медленный старт и гораздо более «тихий» межсетевой экран.

Ограничения ресурсов: cgroups против rctl

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

FreeBSD использует rctl — это подсистема, которую необходимо включить вручную. Учет ресурсов по умолчанию отключен, так как он создает небольшую нагрузку при каждом выделении памяти. Добавьте параметр настройки в /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 во FreeBSD перезагружает их из /etc/rctl.conf, поэтому запишите правило в этот файл и включите службу:

sudo sysrc rctl_enable=YES

Это тот аспект, в котором Docker явно удобнее. Лимит в файле Compose проходит проверку вместе с сервисом, который он ограничивает. Правило rctl — это строка в отдельном файле, ссылающаяся на jail, который определен где-то в другом месте.

Когда ответом является виртуальная машина: bhyve

Jail использует общее ядро с хостом, поэтому некоторые возможности остаются недоступными. Внутри jail нельзя запустить другую версию ядра, загрузить модуль ядра или исполнять Linux-бинарные файлы так, как это делают контейнеры в Linux. В FreeBSD существует слой совместимости с Linux, linuxulator, но он реализует лишь подмножество системных вызовов Linux и не является универсальным решением для запуска произвольных образов Linux.

bhyve — это гипервизор FreeBSD. Это подходящий инструмент, когда вам необходима реальная граница изоляции: другая операционная система, другое ядро или арендатор, с которым вы не хотите использовать общее ядро. Вы платите за это памятью, которая резервируется, а не распределяется динамически, и необходимостью обновлять второе ядро. Это тот же выбор, который вы делаете в Linux между контейнерами и полноценными виртуальными машинами, и именно он определяет, нужен ли вам VPS с поддержкой вложенной виртуализации в качестве основы.

Экосистема — главная причина, по которой большинство команд выбирают Docker

Все, что было сказано выше, касается модели работы. Однако выбор большинства команд определяет масштаб инфраструктуры вокруг каждого решения.

Docker предоставляет Docker Hub и GHCR, docker compose, Kubernetes для случаев, когда одного сервера становится недостаточно, CI-раннеры со встроенной поддержкой контейнеров и возможность быстрого запуска одной командой, описанную в README почти каждого проекта. Jails предлагают дерево портов FreeBSD — обширное и тщательно поддерживаемое, но при этом гораздо меньший набор готовых к запуску пакетов приложений. Если проект публикует только образ контейнера, при использовании FreeBSD вам придется изучать документацию и собирать компоненты самостоятельно.

Jails выигрывают в других аспектах. Они нужны, если вы уже используете ZFS и цените возможность создания снимков (snapshot) и отката (rollback) всего сервиса целиком, если ваши сервисы являются нативными для FreeBSD, если вам требуется полноценное пользовательское окружение (userland) для каждого арендатора вместо одного процесса, или если вы хотите, чтобы ядро, пакетный фильтр, файловая система и документация поддерживались как единая система. Именно это имеют в виду, когда называют FreeBSD целостной ОС. Подробнее об этом можно прочитать в сравнительном обзоре Linux и FreeBSD как серверных платформ и в материале о том, что изменилось во FreeBSD 15 для серверного использования.

Заключительный вывод. Если ваша команда уже работает с Docker, затраты на переход будут ощутимыми, и выгода должна быть конкретной. Не стоит переходить ради качества изоляции: обе модели достаточно близки, и ваша конфигурация значит больше. Переходите, если вам нужен откат целых сервисов на базе ZFS или если вы уже используете FreeBSD.

FAQ

Можно ли запускать Docker-образы в FreeBSD?

Не Linux-образы и не в качестве поддерживаемого решения. В FreeBSD есть поддержка OCI-контейнеров: sudo pkg install -y podman-suite устанавливает Podman, который запускает контейнеры через ocijail — среду выполнения, создающую полноценные jails. Для работы монитора контейнеров требуется смонтировать fdescfs в /dev/fd, а для NAT (трансляции сетевых адресов) контейнеров — pf. Лучше всего работают OCI-образы, нативные для FreeBSD. Для Linux-образов дополнительно требуется слой совместимости с Linux, при этом по состоянию на август 2026 года порт Podman для FreeBSD всё ещё считается экспериментальным. Если ваш стек состоит из Linux-образов, запускайте его на Linux. В семействе RHEL это означает установку Docker на Rocky Linux или AlmaLinux, где Podman уже присутствует в системе как пакет, занимающий команду docker ещё до того, как вы что-либо установили.

Безопаснее ли FreeBSD jails, чем Docker-контейнеры?

Оба решения используют одно ядро хоста, поэтому уязвимость в ядре представляет риск для обоих, и ни одно из них не является тем барьером, который стоит выбирать для работы с заведомо недоверенным кодом. Разница заключается в подходе к настройке. Jail изначально запрещает широкий набор операций, которые вы разрешаете по одному параметру за раз. Docker-контейнер запускается от имени root внутри набора пространств имён (namespaces) с ограниченными привилегиями (capabilities), а дальнейшее ужесточение безопасности выполняется по выбору администратора. На практике конфигурация важнее модели: jail с включёнными allow.mount и allow.raw_sockets не безопаснее, чем грамотно настроенный контейнер.

Как создать резервную копию jail?

Создайте снапшот датасета и отправьте его. Выполните sudo zfs snapshot zroot/jails/containers/web@backup, а затем zfs send этого снапшота в другой пул или в файл, который можно скопировать с сервера. Поскольку jail хранит всё пользовательское окружение в одном датасете, снапшот фиксирует установленные пакеты и данные в согласованном состоянии, включая все файлы конфигурации, которые вы правили вручную. Это противоположность подходу Docker, где вы делаете резервные копии именованных томов и файла Compose, а остальное пересобираете из образа.

Нужен ли мне BastilleBSD или достаточно базовой системы?

Базовой системы достаточно, и с неё лучше начинать. jail.conf, jls, jexec и service jail start охватывают всю модель работы, и, освоив их, вы сможете разобраться с любым хостом FreeBSD, не изучая специфические инструменты этого хоста. Bastille — это слой удобства поверх базовых средств: он разворачивает релизы, создаёт тонкие (thin) jails, применяет шаблоны и прописывает правила перенаправления pf за вас. Сначала изучите базовые команды, а затем добавьте Bastille, когда количество jails сделает ручной ввод команд утомительным.