在FreeBSD 14.3上部署轻量级Linux jail环境 仅仅占用10M内存

Creating a Linux Jail 手册:

https://docs.freebsd.org/en/books/handbook/jails/#thin-jail

FreeBSD系统里创建Linux的jail的思路是:

跟主系统启动Linux兼容层协议一样。主系统启动Linux是使用FreeBSD内核,然后使用Linux兼容层来实现Linux软件的运行(具体是Linux ABI 实现Linux的调用)。所以创建Linux jail,思路就是先创建一个FreeBSD的jail,然后里面使用debootstrap安装Ubuntu兼容系统。

先启动FreeBSD主系统linux兼容协议

配置linux兼容

复制代码
sysrc linux_enable="YES"

启动linux兼容协议

复制代码
service linux start

这样启动后,linux兼容要多大约内存耗费增加300k

使用OpenZFS创建一个轻量级jail的快照 a Thin Jail Using OpenZFS Snapshots

这部跟创建轻量级FreeBSD jail的方法一模一样,完全可以参考官网a Thin Jail Using OpenZFS Snapshots这部分,除了设置的名字不一样(名字也可以跟官方一样用ubuntu,但是我还是喜欢用ubjail1这个名字),其它都可以跟官方一样。

参考这里:https://skywalk.blog.csdn.net/article/details/154576901

先创建目录

复制代码
zfs create -o mountpoint=/usr/local/jails zroot/jails
zfs create zroot/jails/media
zfs create zroot/jails/templates
zfs create zroot/jails/containers

创建一个模版

复制代码
zfs create -p zroot/jails/templates/14.3-RELEASE

下载linux的base.txz

可以使用阿里镜像,非常快!

复制代码
fetch https://download.freebsd.org/ftp/releases/amd64/amd64/14.3-RELEASE/base.txz -o /usr/local/jails/media/14.3-RELEASE-base.txz

# 阿里镜像 非阿里云也可以用
fetch https://mirrors.aliyun.com/freebsd/releases/amd64/14.3-RELEASE/base.txz -o /usr/local/jails/media/14.3-RELEASE-base.txz

下载完成解压

复制代码
tar -xf /usr/local/jails/media/14.3-RELEASE-base.txz -C /usr/local/jails/templates/14.3-RELEASE --unlink

设定jail虚拟机相关

待用户空间提取到模板目录中,就需要通过以下命令将时区和 DNS 服务器文件复制到模板目录中:

复制代码
cp /etc/resolv.conf /usr/local/jails/templates/14.3-RELEASE/etc/resolv.conf
cp /etc/localtime /usr/local/jails/templates/14.3-RELEASE/etc/localtime

升级补丁

将文件移动到模板中后,接下来的步骤是通过以下命令更新到最新的补丁级别:

复制代码
freebsd-update -b /usr/local/jails/templates/14.3-RELEASE/ fetch install

生成快照

复制代码
zfs snapshot zroot/jails/templates/14.3-RELEASE@base

创建Linux jail

创建一个普通的FreeBSD轻量级jail ,名字叫ubjail1,所以目录放在了zroot/jails/containers/ubjail1

复制代码
zfs clone zroot/jails/templates/14.3-RELEASE@base zroot/jails/containers/ubjail1

一直到这一步,创建Linux jail的过程跟创建FreeBSD jail的步骤一模一样,就是创建了一个FreeBSD jail的快照。

启动和配置jail

跟普通的FreeBSD轻量级jail不一样,这里没有jail的配置文件(不先配置,先启动,最后还是要写一个配置文件),而是在启动jail的时候这样写命令配置并启动jail:

复制代码
jail -cm \
    name=ubjail1 \
    host.hostname="ubjail1.example.com" \
    path="/usr/local/jails/containers/ubjail1" \
    interface="igb0" \
    ip4.addr="192.168.1.12" \
    exec.start="/bin/sh /etc/rc" \
    exec.stop="/bin/sh /etc/rc.shutdown" \
    mount.devfs \
    devfs_ruleset=4 \
    allow.mount \
    allow.mount.devfs \
    allow.mount.fdescfs \
    allow.mount.procfs \
    allow.mount.linprocfs \
    allow.mount.linsysfs \
    allow.mount.tmpfs \
    allow.raw_sockets \
    allow.socket_af \
    allow.sysvipc \
    enforce_statfs=1

注意,这里加上了4句官方手册里没有句子,否则网络不会通:

复制代码
    allow.mount.tmpfs \
    allow.raw_sockets \
    allow.socket_af \
    allow.sysvipc \

启动成功:

复制代码
ELF ldconfig path: /lib /usr/lib /usr/lib/compat
32-bit compatibility ldconfig path: /usr/lib32
Updating motd:.
Creating and/or trimming log files.
Clearing /tmp (X related).
Updating /var/run/os-release done.
Starting syslogd.
Starting cron.

Sat Nov 15 11:56:01 CST 2025

这时候jls看看,可以看到确实启动成功了

复制代码
jls
   JID  IP Address      Hostname                      Path
     8                  wwwjail                       /usr/local/jails/containers/wwwjail
     9                  datajail                      /usr/local/jails/containers/datajail
    14  192.168.1.12    ubjail1.example.com           /usr/local/jails/containers/ubjail1

配置jail的Linux部分

登录jail

复制代码
jexec -u root ubjail1

可以看到当前还是FreeBSD的jail

复制代码
jexec -u root ubjail1
root@ubjail1:/ # uname -a
FreeBSD ubjail1.example.com 14.3-RELEASE FreeBSD 14.3-RELEASE releng/14.3-n271432-8c9ce319fef7 GENERIC amd64

安装jammy

在jail里安装debootstrap,然后再安装Ubuntu的jammy版本:

复制代码
pkg install debootstrap
debootstrap jammy /compat/ubuntu

如果pkg速度慢,就设置镜像

创建路径及文件 /usr/local/etc/pkg/repos/USTC.conf 来覆盖配置,文件内容如下:

复制代码
ustc: { 
  url: "https://mirrors.ustc.edu.cn/freebsd-pkg/${ABI}/quarterly"
}
FreeBSD: { enabled: no }

debootstrap jammy /compat/ubuntu 的速度非常慢,不知道该怎么解决。

找到解决方法了:

在运行 debootstrap 命令时,可以通过 --mirror 参数指定国内的镜像源地址。以下是一些稳定且速度较快的国内镜像源:

‌清华大学镜像源‌:https://mirrors.tuna.tsinghua.edu.cn/ubuntu/

‌中国科学技术大学镜像源 (USTC)‌:https://mirrors.ustc.edu.cn/ubuntu/

‌华为云镜像源‌:https://mirrors.huaweicloud.com/ubuntu/

‌阿里云镜像源‌:https://mirrors.aliyun.com/ubuntu/

‌网易镜像源‌:http://mirrors.163.com/ubuntu/

比如可以这样写:

复制代码
 debootstrap jammy /compat/jammy https://mirrors.aliyun.com/ubuntu/

然后写一个配置文件

写到/etc/jail.conf文件中:

复制代码
ubjail1 {
  # STARTUP/LOGGING
  exec.start = "/bin/sh /etc/rc";
  exec.stop = "/bin/sh /etc/rc.shutdown";
  exec.consolelog = "/var/log/jail_console_${name}.log";

  # PERMISSIONS
  allow.raw_sockets;
  exec.clean;
  mount.devfs;
  devfs_ruleset = 4;

  # HOSTNAME/PATH
  host.hostname = "${name}";
  path = "/usr/local/jails/containers/${name}";

  # NETWORK
  ip4.addr = 192.168.1.12;
  interface = igb0;

  # MOUNT
  mount += "devfs     $path/compat/ubuntu/dev     devfs     rw  0 0";
  mount += "tmpfs     $path/compat/ubuntu/dev/shm tmpfs     rw,size=1g,mode=1777  0 0";
  mount += "fdescfs   $path/compat/ubuntu/dev/fd  fdescfs   rw,linrdlnk 0 0";
  mount += "linprocfs $path/compat/ubuntu/proc    linprocfs rw  0 0";
  mount += "linsysfs  $path/compat/ubuntu/sys     linsysfs  rw  0 0";
  mount += "/tmp      $path/compat/ubuntu/tmp     nullfs    rw  0 0";
  mount += "/home     $path/compat/ubuntu/home    nullfs    rw  0 0";
}

停机

复制代码
service jail onestop ubjail1

重新启动

按照常规jail的方法启动

复制代码
service jail start ubjail1

进入jail

注意进入方式跟普通FreeBSD jail不同,因为如果用同样的命令,进入的就是FreeBSD,只有靠chroot,可以进入Linux兼容环境

复制代码
jexec ubjail1 chroot /compat/ubuntu /bin/bash

看看当前系统

复制代码
jexec ubjail1 chroot /compat/ubuntu /bin/bash
root@ubjail1:/# uname -a
Linux ubjail1 5.15.0 FreeBSD 14.3-RELEASE releng/14.3-n271432-8c9ce319fef7 GENERIC x86_64 x86_64 x86_64 GNU/Linux

果然是linux了 。

后续工作

设置Ubuntu jammy加速

修改/etc/apt/sources.list文件,

复制代码
# 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-updates main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-updates main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-backports main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-backports main restricted universe multiverse
 
# 以下安全更新软件源包含了官方源与镜像站配置,如有需要可自行修改注释切换
deb http://security.ubuntu.com/ubuntu/ jammy-security main restricted universe multiverse
# deb-src http://security.ubuntu.com/ubuntu/ jammy-security main restricted universe multiverse
 
# 预发布软件源,不建议启用
# deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-proposed main restricted universe multiverse
# # deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-proposed main restricted universe multiverse

查看当前内存占用

Mem: 21M Active

linux内核起来还是有点占内存的,一个Linux jail几乎比主机+两个FreeBSD jail占用的都多。

但是也总共只占用了21M,还是相当可以的。全部内存信息:Mem: 20M Active, 259M Inact, 2451M Wired, 5068M Free

总结

这大约是第一次整明白FreeBSD轻量级Linux jail ,以前大部分时候都是用easyjail或者cbsd自动生成的。而且cbsd自动生成的Linux jail,有时候启动进去还是FreeBSD,这里也弄明白了,因为如果是用的Linux兼容技术,那么就不能直接用/bin/bash ,那个是FreeBSD,而是应该用chroot /compat/linux/ /bin/bash 进入的才是Linux jail !

看着步骤还是非常繁琐,直接用cbsd来安装要方便很多,可以参考这篇文档:https://skywalk.blog.csdn.net/article/details/139719880

调试

jail -cm启动的时候报错

jail: mount.devfs: /usr/local/jails/ubjail1/dev: No such file or directory

ifconfig: ioctl (SIOCDIFADDR): Can't assign requested address

jail: /sbin/ifconfig igb0 inet 192.168.1.22/24 -alias: failed

原来的命令:

复制代码
jail -cm \
    name=ubjail1 \
    host.hostname="ubjail1.example.com" \
    path="/usr/local/jails/ubjail1" \
    interface="igb0" \
    ip4.addr="192.168.1.22" \
    exec.start="/bin/sh /etc/rc" \
    exec.stop="/bin/sh /etc/rc.shutdown" \
    mount.devfs \
    devfs_ruleset=4 \
    allow.mount \
    allow.mount.devfs \
    allow.mount.fdescfs \
    allow.mount.procfs \
    allow.mount.linprocfs \
    allow.mount.linsysfs \
    allow.mount.tmpfs \
    enforce_statfs=1

手工创建这个目录试试:

sudo mount -t devfs devfs /usr/local/jails/ubjail1/dev

哦了,没有dev的报错了。后来弄明白了,不是这个问题,是目录写错了,应该是/usr/local/jails/containers/ubjail1 配置文件应该是:

复制代码
jail -cm \
    name=ubjail1 \
    host.hostname="ubjail1.example.com" \
    path="/usr/local/jails/containers/ubjail1" \
    interface="igb0" \
    ip4.addr="192.168.1.12" \
    exec.start="/bin/sh /etc/rc" \
    exec.stop="/bin/sh /etc/rc.shutdown" \
    mount.devfs \
    devfs_ruleset=4 \
    allow.mount \
    allow.mount.devfs \
    allow.mount.fdescfs \
    allow.mount.procfs \
    allow.mount.linprocfs \
    allow.mount.linsysfs \
    allow.mount.tmpfs \
    enforce_statfs=1

修改启动文件参数后,配置和启动完成:

复制代码
ELF ldconfig path: /lib /usr/lib /usr/lib/compat
32-bit compatibility ldconfig path: /usr/lib32
Updating motd:.
Creating and/or trimming log files.
Clearing /tmp (X related).
Updating /var/run/os-release done.
Starting syslogd.
Starting cron.

Sat Nov 15 11:56:01 CST 2025

启动后无法连外网

发现没有ip

复制代码
igb0: flags=1008843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST,LOWER_UP> metric 0 mtu 1500
        options=4e527bb<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,TSO4,TSO6,LRO,WOL_MAGIC,VLAN_HWFILTER,VLAN_HWTSO,RXCSUM_IPV6,TXCSUM_IPV6,HWSTATS,MEXTPG>
        ether 00:e2:69:13:67:f6
        media: Ethernet autoselect (1000baseT <full-duplex>)
        status: active

jail -cm \
    name=ubjail1 \
    host.hostname="ubjail1.example.com" \
    path="/usr/local/jails/containers/ubjail1" \
    interface="igb0" \
    ip4.addr="10.168.1.12" \
    exec.start="/bin/sh /etc/rc" \
    exec.stop="/bin/sh /etc/rc.shutdown" \
    mount.devfs \
    devfs_ruleset=4 \
    allow.mount \
    allow.mount.devfs \
    allow.mount.fdescfs \
    allow.mount.procfs \
    allow.mount.linprocfs \
    allow.mount.linsysfs \
    allow.mount.tmpfs \
    enforce_statfs=1

在jail内部修改ip试试

复制代码
echo 'ifconfig_igb0="inet 192.168.1.12 netmask 255.255.255.0"'

不行,用命令试试

复制代码
ifconfig_igb0="inet 192.168.1.12 netmask 255.255.255.0"
defaultrouter="192.168.1.1"

不行,jail内部会报错:

复制代码
/etc/netstart
Starting devd.
devd: Can't open devctl device /dev/devctl: No such file or directory
/etc/rc.d/devd: WARNING: failed to start devd
/etc/rc.d/hostid: WARNING: hostid: unable to figure out a UUID from DMI data, generating a new one
Setting hostuuid: 0f360e44-9944-41e5-b2ca-fdb949f43733.
Setting hostid: 0xbc850509.
ifconfig: up: permission denied
ifconfig: ioctl (SIOCAIFADDR): Operation not permitted
ifconfig: ioctl (SIOCAIFADDR): Operation not permitted
ifconfig: up: permission denied
Starting Network: lo0 igb0 cbsdbr0.
lo0: flags=1008049<UP,LOOPBACK,RUNNING,MULTICAST,LOWER_UP> metric 0 mtu 16384
        options=680003<RXCSUM,TXCSUM,LINKSTATE,RXCSUM_IPV6,TXCSUM_IPV6>
        groups: lo
igb0: flags=1008843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST,LOWER_UP> metric 0 mtu 1500
        options=4e527bb<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,TSO4,TSO6,LRO,WOL_MAGIC,VLAN_HWFILTER,VLAN_HWTSO,RXCSUM_IPV6,TXCSUM_IPV6,HWSTATS,MEXTPG>
        ether 00:e2:69:13:67:f6
        media: Ethernet autoselect (1000baseT <full-duplex>)
        status: active
cbsdbr0: flags=1008843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST,LOWER_UP> metric 0 mtu 1500
        options=0
        ether 58:9c:fc:10:ff:83
        id 00:00:00:00:00:00 priority 32768 hellotime 2 fwddelay 15
        maxage 20 holdcnt 6 proto rstp maxaddr 2000 timeout 1200
        root id 00:00:00:00:00:00 priority 32768 ifcost 0 port 0
        groups: bridge
add host 127.0.0.1: gateway lo0 fib 0: Operation not permitted
add net default: gateway 192.168.1.1 fib 0: Operation not permitted
sysctl: net.inet.icmp.bmcastecho=0: Operation not permitted
sysctl: net.inet.icmp.drop_redirect=0: Operation not permitted
sysctl: net.inet.icmp.log_redirect=0: Operation not permitted
sysctl: net.inet.ip.forwarding=0: Operation not permitted
sysctl: net.inet.ip.sourceroute=0: Operation not permitted
sysctl: net.inet.ip.accept_sourceroute=0: Operation not permitted
sysctl: net.link.ether.inet.proxyall=0: Operation not permitted
add host ::1: gateway lo0 fib 0: Operation not permitted
add net fe80::: gateway ::1 fib 0: Operation not permitted
add net ff02::: gateway ::1 fib 0: Operation not permitted
add net ::ffff:0.0.0.0: gateway ::1 fib 0: Operation not permitted
add net ::0.0.0.0: gateway ::1 fib 0: Operation not permitted
sysctl: net.inet6.ip6.forwarding=0: Operation not permitted

尝试加入这几句

复制代码
    allow.raw_sockets \
    allow.socket_af \
    allow.sysvipc \

jail -cm \
    name=ubjail1 \
    host.hostname="ubjail1.example.com" \
    path="/usr/local/jails/containers/ubjail1" \
    interface="igb0" \
    ip4.addr="192.168.1.12" \
    exec.start="/bin/sh /etc/rc" \
    exec.stop="/bin/sh /etc/rc.shutdown" \
    mount.devfs \
    devfs_ruleset=4 \
    allow.mount \
    allow.mount.devfs \
    allow.mount.fdescfs \
    allow.mount.procfs \
    allow.mount.linprocfs \
    allow.mount.linsysfs \
    allow.mount.tmpfs \
    allow.raw_sockets \
    allow.socket_af \
    allow.sysvipc \
    enforce_statfs=1

网络终于通了,问题解决

apt update的时候报错 Updates for this repository will not be applied.

复制代码
apt update
Get:1 https://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy InRelease [270 kB]
Get:2 https://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy-updates InRelease [128 kB]
Get:3 https://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy-backports InRelease [127 kB]
Get:4 http://security.ubuntu.com/ubuntu jammy-security InRelease [129 kB]
Get:5 https://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy/main amd64 Packages [1395 kB]
Get:6 https://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy/main Translation-en [510 kB]
Get:7 https://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy/restricted amd64 Packages [129 kB]
Get:8 https://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy/restricted Translation-en [18.6 kB]
Get:9 https://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy/universe amd64 Packages [14.1 MB]
Get:10 https://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy/universe Translation-en [5652 kB]
Get:11 https://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy/multiverse amd64 Packages [217 kB]
Get:12 https://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy/multiverse Translation-en [112 kB]
Reading package lists... Done
E: Release file for https://mirrors.tuna.tsinghua.edu.cn/ubuntu/dists/jammy-updates/InRelease is not valid yet (invalid for another 6h 36min 10s). Updates for this repository will not be applied.
E: Release file for https://mirrors.tuna.tsinghua.edu.cn/ubuntu/dists/jammy-backports/InRelease is not valid yet (invalid for another 4h 37min 57s). Updates for this repository will not be applied.
E: Release file for http://security.ubuntu.com/ubuntu/dists/jammy-security/InRelease is not valid yet (invalid for another 6h 33min 25s). Updates for this repository will not be applied.

我的理解是要等6个小时之后才可以update ?

相关推荐
知南x2 小时前
【STM32MP157 异核通信框架学习篇】(10)Linux下Remoteproc相关API (下)
linux·stm32·学习
Tipriest_2 小时前
Linux 环境变量的添加与查看详解
linux·环境变量
敏姐的后花园3 小时前
模考倒计时网页版
java·服务器·前端
牢七3 小时前
新linux
linux
keep__go4 小时前
spark 单机安装
大数据·运维·分布式·spark
HIT_Weston6 小时前
27、【Ubuntu】【远程开发】内网穿透:CA 签名
linux·运维·ubuntu
猫小呆6 小时前
Weaviate服务器部署笔记
服务器·weaviate
M158227690556 小时前
工业互联利器!EtherNet/IP 转 ModbusTCP 网关,让跨协议通信零门槛
服务器·网络·tcp/ip
阿巴~阿巴~6 小时前
基于UDP协议的英汉翻译服务系统:从网络通信到字典查询的完整机制
linux·服务器·网络·网络协议·udp协议·套接字绑定·英汉翻译服务系统