Docker во FreeBSD через bhyve
Вдохновившись установкой FreeBSD на VPS, я решил поинтересоваться - а можно ли туда прикрутить Docker? Сначала я мыслил в сторону эмуляции Linux, но оказалось, что актуальному Докеру нужны cgroups, которых в эмуляции нет. Значит остаются только виртуальные машины. Родной гипервизор фряхи - bhyve, однако в уже виртуализированной FreeBSD (попробовал сначала в VirtualBox) нужные модули ядра скорее не загружаются. Таким образом, нужно реальное железо?..
Поставил систему на завалявшийся у меня внешний SSD, изготовленный самостоятельно из китайских комплектующих. Было немного страшно, когда установщик вывел список разделов на всех дисках (хотя я определенно выбирал для разбиения «флешку»), но, к счастью, ничего не затер. Для работы с виртуальной машиной понадобится окружение рабочего стола, какое же мы установим?.. Ни за что не догадаетесь!
KDE
Пока что мы, конечно, в командной строке под root. Поехали:
pkg install kde5 sddm xorg firefox
Вроде обошелся без plasma5-sddm-kcm, да и некий периодически упоминаемый hald_service тоже уже не нужен как бы… Но при всем обилии устанавливаемых в рамках kde5 программ почему-то отсутствует браузер – предлагаю сразу установить Firefox (или какой-то другой, например попробовать konqueror).
Кстати вместо kde5 можно ограничиться лишь plasma5-plasma konsole remmina-lite
, это будет минимальная установка +RDP/VNC клиент – скачивать примерно гигабайт вместо двух.
После установки – включить, поднастроить сервисы.
В /etc/rc.conf добавить:
dbus_enable="YES"
sddm_enable="YES"
В /etc/sysctl.conf добавить:
net.local.stream.recvspace=65536
net.local.stream.sendspace=65536
Какая установлена видеокарта?
pciconf -lv|grep -B4 VGA
Установить драйвера. В моем случае – для Radeon 5700XT – amdgpu
(хотя какое-то firmware вроде установщик ОС ставил ):
pkg install drm-kmod
sysrc kld_list+=amdgpu
Если не создавали пользователя, то стоит создать сейчас – под root не пустит.
adduser
На этапе добавления групп предлагаю указать wheel (чтобы можно было делать su root
в консоли) и video (требуется для работы xorg). Есть, конечно, подозрение, что надо бы еще и sudo
установить и настроить, но для нашей задачи этого не потребовалось.
Если же пользователь есть, то добавляем его в нужные группы через pw
:
pw groupmod video -m username
Вот теперь вроде бы можно перезагружаться и, если я ничего не упустил, насладиться окружением рабочего стола. Главное не забыть выбрать X11 в едва заметном поле выбора слева внизу, а то там Wayland может оказаться (вроде как такой вариант официально не поддерживается).
vm-bhyve
Я думаю, работать с «голым» bhyve перебор даже для меня, так что установим простой менеджер. Тем более непонятно, как «в рукопашную» машины будут стартовать при загрузке ОС (в смысле не особо хочется заморачиваться еще и с написанием сервисов).
Подготовка
Как обычно, устанавливаем из пакетов:
pkg install vm-bhyve
Все-таки будем ориентироваться на UFS, поэтому просто создаем директорию. Включаем сервис и указываем ее в настройках:
mkdir /usr/local/vm
sysrc vm_enable="YES"
sysrc vm_dir="/usr/local/vm"
Инициализируем:
vm init
Хм, отрабатывает быстро и молча. Похоже просто создается несколько директорий и файлов в указанной vm_dir (согласно документации, еще включаются необходимые модули ядра). Далее предлагается скопировать шаблоны, но я не уверен, что стоит их прямо все копировать.
Собственно вопрос, а какой из Linux'ов взять? Сначала думал было Alpine из-за компактности, но наверное лучше будет взять Arch из-за системы rolling release и нашего любимого systemd (любимый ведь?.. Ну, если не нами, то так хотя бы Docker'ом). Плюс библиотеки там стандартные сишные (в Alpine musl – якобы на что-то может отрицательно влиять).
Так что скопируем шаблон для Arch Linux...
cp /usr/local/share/examples/vm-bhyve/arch.conf /usr/local/vm/.templates/
Или не копируем, потому что результат будет отличаться процентов на 50 – шаблон необходимо переделать. С самого начала нас встречает загрузчик grub
. Нужный для его работы пакет grub2-bhyve какой-то уже подозрительный, поскольку за ним никто не присматривает. Предлагаю поменять загрузчик на uefi
, соответственно удалить настройки grub из шаблона и разрешить использовать переменные UEFI (uefi_vars="yes"
).
Далее, если 1 ядро еще туда-сюда, то на 512 оперативки как будто в принципе ничего не работает (ошибки типа мало ресурсов или т.п. «синие экраны»). Так что делаем минимум гиг и включаем графику, поскольку иначе в консоли что-то дальше загрузочного меню ничего не происходит.
loader="uefi"
cpu=1
memory=1024M
network0_type="virtio-net"
network0_switch="public"
disk0_type="virtio-blk"
disk0_name="disk0.img"
uefi_vars="yes"
graphics="yes"
graphics_listen="127.0.0.1"
Соответственно для поддержки UEFI установим пакет:
pkg install bhyve-firmware
Скачиваем ISO, например с Яндекса:
vm iso https://mirror.yandex.ru/archlinux/iso/latest/archlinux-x86_64.iso
Если при запуске команд vm
появляется ошибка ERROR: unable to load vmm.ko!, то скорее всего вы пытаетесь работать с bhyve в уже виртуализированной FreeBSD.
Создаем машину по шаблону с диском на 8 гигабайт:
vm create -t arch -s 8G arch
Разумеется, эти самые 8 гигабайт будут выделены сразу. С другой стороны, если есть возможность, лучше «подсыпать» этих самых гигов.
Виртуальная сеть
Предлагаю сразу же настроить локальный NAT и DHCP, чтобы назначать IP виртуальным машинам через него (я это сделаю в стиле VirtualBox). Итак, создаем сетевой мост:
vm switch create -a 192.168.56.1/24 public
vm switch add public re0
Соответственно public
– имя моста (оно используется в настройках сети шаблона виртуальной машины), а re0
– ваш основной сетевой интерфейс (можно проверить ifconfig'ом, обычно в инструкциях пишут em0, но у меня вот на сей раз re0).
Включаем pf:
sysrc pf_enable=YES
sysrc gateway_enable=YES
Файл /etc/pf.conf – вот прямо без ничего, один только NAT:
nat on re0 from {192.168.56.0/24} to any -> (re0)
Конечно, в идеале бы настроить все как следует, но это, как говорится, выходит за рамки статьи. В каком-то виде я настраивал pf для веб-сервера.
Что касается DHCP, то авторы vm-bhyve пользуются dnsmasq, хотя во FreeBSD условно стандартным является isc-dhcp44-server (по крайней мере описывается в руководстве). Давайте я все же настрою «штатный»:
pkg install isc-dhcp44-server
sysrc dhcpd_enable="YES"
sysrc dhcpd_ifaces="vm-public"
Редактируем /usr/local/etc/dhcpd.conf. В нем изначально много всего лишнего, поэтому комментируем (или удаляем) все примерно начиная с log-facility local7;
. Формируем собственную конфигурацию:
#option domain-name "example.org";
option domain-name-servers 77.88.8.8, 77.88.8.1;
# значения по умолчанию
default-lease-time 600;
max-lease-time 7200;
# подсеть в стиле VirtualBox
subnet 192.168.56.0 netmask 255.255.255.0 {
range 192.168.56.101 192.168.56.254;
option routers 192.168.56.1;
}
# фиксированный ip для виртуалки Arch Linux
host arch {
hardware ethernet 58:9c:fc:0d:7a:81;
fixed-address 192.168.56.10;
}
С option domain-name
толком непонятно, что делать, так что решил закомментировать ее вовсе. Серверы имен пусть будут Яндексовские, а MAC-адрес сетевого адаптера виртуальной машины смотрим в /usr/local/vm/arch/arch.conf (у меня, соответственно, 58:9c:fc:0d:7a:81).
Запустим, наверное, сразу (хотя возможно лучше перезагрузить всю FreeBSD):
service pf start
service isc-dhcpd start
По идее теперь можно приступать к установке.
Установка Arch Linux
Запускаем виртуальную машину в режиме загрузки с образа диска:
vm install arch archlinux-x86_64.iso
И подключаемся к ней по VNC на присвоенный порт – проверить через vm list
(скорее всего это будет 5900).
По секрету скажу, что первоначально я очень сильно намучился с KRDP (поскольку он входит в полную установку KDE), в частности с захватом клавиш. Поэтому рекомендую воспользоваться другим клиентом, например Remmina. Там, конечно, тоже все немного странно, но хотя бы есть глубоко запрятанная возможность отправить содержимое буфера обмена в виде нажатий клавиш (результат впрочем тоже может удивить). Хорошо хоть захват этих самых клавиш работает как положено – если окно активно, значит печатаем в виртуальной машине, а нет – значит нет.
Итак, система, я надеюсь, загружена, и в первую очередь нас интересует, добились ли мы нужного эффекта настройкой виртуальной сети:
ip addr
ping -c2 freebsd.org
О, да! IP-адрес сетевому адаптеру назначен, DNS работает, пинг «вовне» идет.
Что ж, можем устанавливать. Специально ради этого я написал статью, правда там фигурирует VirtualBox в качестве гипервизора, так что будут незначительные нюансы. Поэтому здесь приведу «скрипт» установки практически без пояснений.
Разрешаем подключение по SSH:
echo 'PermitRootLogin Yes' >> /etc/ssh/sshd_config
passwd
systemctl restart sshd
Размечаем диск, например, через fdisk:
fdisk -l
fdisk /dev/vda
Схема:
Device Start End Sectors Size Type
/dev/vda1 2048 2099199 2097152 1G EFI System
/dev/vda2 2099200 4196351 2097152 1G Linux swap
/dev/vda3 4196352 16775167 12578816 6G Linux root (x86-64)
Продолжаем установку:
mkfs.fat -F 32 /dev/vda1
mkswap /dev/vda2
mkfs.btrfs /dev/vda3
mount -o compress=zstd /dev/vda3 /mnt
mount --mkdir /dev/vda1 /mnt/boot
swapon /dev/vda2
pacstrap -K /mnt base linux btrfs-progs nano efibootmgr openssh
genfstab -U /mnt >> /mnt/etc/fstab
arch-chroot /mnt
ln -sf /usr/share/zoneinfo/UTC /etc/localtime
hwclock --systohc
Внимательный читатель обратил внимание, что для корневой файловой системы я влупиул btrfs с компрессией для экономии места. UUID ФС в моем случае a0769764-52c5-4282-b63e-274747c1f76e. Ну и UTC пусть часовым поясом будет. Далее необходимо отредактировать /etc/locale.gen – раскомментировать en_US.UTF-8 UTF-8
и заодно ru_RU.UTF-8 UTF-8
.
Далее:
locale-gen
echo 'LANG=en_US.UTF-8' > /etc/locale.conf
echo 'arch-vm' > /etc/hostname
efibootmgr --create --disk /dev/vda --part 1 --label "Arch Linux" --loader /vmlinuz-linux --unicode 'root=UUID=a0769764-52c5-4282-b63e-274747c1f76e rw initrd=\initramfs-linux.img'
systemctl enable sshd
echo 'PermitRootLogin Yes' >> /etc/ssh/sshd_config
systemctl enable systemd-networkd
systemctl enable systemd-resolved
Создадим файл настройки сети, например /etc/systemd/network/10-wired.network:
[Match]
Name=enp0s5
[Link]
RequiredForOnline=routable
[Network]
DHCP=yes
Устанавливаем пароль root, выходим из chroot и выключаем машину:
passwd
exit
poweroff
Запускаем виртуалку в обычном режиме:
vm start arch
Если все в порядке (проверяем подключениями по VNC и SSH), то ставим ее в «автозапуск»:
sysrc vm_list=arch
That's it!
Docker
Общая папка
vm-bhyve предлагает для этого VirtIO 9p. Что ж… Вероятно сначала надо бы машину выключить. В стиле Arch Linux на хосте создадим каталог /srv/docker и добавим диск в настройки («вручную» редактируем /usr/local/vm/arch/arch.conf или vm configure arch
):
disk1_type="virtio-9p"
disk1_name="docker=/srv/docker"
disk1_dev="custom"
Запускаем Arch Linux и пробуем смонтировать:
mount --mkdir -t 9p -o trans=virtio docker /srv/docker
Внезапно получилось без установки каких-либо дополнительных пакетов. Проверяем создание файлов там и сям – все работает, права доступа и пользователь по умолчанию (644 root:wheel на хосте и 644 root:root в гостевой ОС). Но в целом права вроде бы транслируются.
Монтируем на постоянной основе – добавляем запись в /etc/fstab (в Arch Linux):
# shared directory
docker /srv/docker 9p trans=virtio,rw 0 0
Перезагружаем Arch Linux или перемонтируем:
umount /srv/docker
systemctl daemon-reload
mount /srv/docker
Переходим к установке Docker.
Установка в Arch Linux
Здесь все точно так же, как и в ранее упомянутой статье. Установка из пакетов:
pacman -S docker docker-compose docker-buildx
У нас btrfs, поэтому сначала создадим подтом:
btrfs subvolume create /var/lib/docker
Скорее всего каталога /etc/docker еще нет, поэтому создадим его (mkdir /etc/docker
) и добавим файл /etc/docker/daemon.json для использования нужного нам драйвера хранилища:
{
"storage-driver": "btrfs"
}
Запускаемся:
systemctl enable --now docker
Как обычно, проверить установку можно командами docker info
и/или docker run hello-world
.
Клиент во FreeBSD
Устанавливаем клиента на хост:
pkg install docker
Что-то старый какой-то (18-й) и опять-таки беспризорный. Ладно, на что-нибудь наверное сгодится. Но как мы получим доступ с хоста к сокету Докера в виртуальной машине? С помощью туннеля SSH.
Под пользователем, который будет работать с клиентом докера, генерируем ключ SSH и добавляем его в authorized_keys в Arch Linux:
ssh-keygen
cat ~/.ssh/id_rsa.pub | ssh root@192.168.56.10 "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
Чтобы каждый раз не указывать хост, добавим в ~/.cshrc (при условии, что оболочка csh):
setenv DOCKER_HOST ssh://root@192.168.56.10
Перезайдем в консоль и проверим:
docker info
Должна быть выведена информация, аналогичная Arch Linux.
Пример
Начинаем делать под root на хосте (FreeBSD). Добавим пользователя с uid и gid 33, пусть называется как в Docker – www-data:
pw useradd www-data -u 33 -d /nonexistent -s /usr/sbin/nologin -c 'Docker Web user'
Создадим каталог /srv/docker/html, а в нем простейший файл index.php:
<?php phpinfo(); ?>
Меняем владельца:
chown -R www-data:www-data /srv/docker/html
Если клиент докера настроен под другим пользователем, то переключаемся в его консоль и:
cd /srv/docker/html
docker run -d -p 80:80 --name web -v "$PWD":/var/www/html php:8.4-apache
Проброс текущей директории $PWD
возможен благодаря одинаковым путям во FreeBSD и Arch Linux. Ждем, пока скачается образ и запустится контейнер, после чего заходим «по IP». Должны отобразиться сведения о PHP.
Для приличия останавливаем и удаляем контейнер.
docker stop web
docker container rm web
К сожалению, docker compose
есть только непосредственно в Arch Linux (думаю сверхустаревший docker-compose 1.x рассматривать не стоит). К счастью, работать с файлами можно с хоста.
Заключение
По сравнению с VirtualBox, где можно «натыкать» конфигурацию мышкой и в немалой степени все уже сделано за нас, работа с bhyve потребует довольно длительной настройки (во всяком случае виртуальной сети). Как говорится, долго запрягать, зато потом… Кстати мне наоборот понравилось, что vm-bhyve в актуальных версиях не навязывает каких-то конкретных настроек NAT и DHCP, да и по VNC к виртуальной машине можно подключаться любым клиентом. Еще один плюс – заработавшая «из коробки» 9p с нормальной работой файловых прав доступа.
Но виртуальную машину bhyve нельзя так просто взять и запустить на VDS/VPS – на одном из них все «отвалилось» уже на этапе vm init
, зато на другом внезапно запустилась. В целом система больше актуальна для рабочей станции или выделенного сервера. В этом случае можно посмотреть более продвинутый менеджер – CBSD. Кстати тамошняя статья про Docker (к сожалению, устаревшая) тоже в немалой степени сподвигла на данный эксперимент.
Категория: Программирование, веб | Опубликовано 12.06.2025 | Редакция от 05.07.2025
Похожие материалы
Веб-сервер на FreeBSD с использованием клеток
Здесь вам не Докер, а клетки (jails) - будем говорить, это контейнеры FreeBSD, когда это еще не было мейнстримом (на минуточку, они появились еще во FreeBSD 4.x - 2000 год). Практический смысл в моем случае - неким образом изолированно использовать разные версии PHP, ну и чуть ближе познакомиться с технологией, с которой я уже сталкивался при обзоре TrueNAS. Основано, как говорится, на реальных событиях - я переносил сайты на Drupal 7.x и Yii с сервера на Linux.
FreeBSD на VPS
Продолжаю устанавливать что-нибудь этакое на VPS. На сей раз решил, так сказать, вернуться к истокам - ведь когда-то многие веб-сервера были на фряхе, а также посмотреть, насколько она компактна сама по себе и в плане ресурсоемкости.