昨晚把教程写完后,我就去睡了,还好今天放假不用担心第二天的班
今天一早醒来就看到大家对我的 “小众虚拟机” 提出的宝贵建议了,在此十分感谢各位提的建议,后面我完成教程后会将 “小众虚拟机” 发出来(含源码和启动镜像),各位如有需要欢迎下载使用哈
[!note]- 但是我想说
不过我想大家可能对我创作的初心有点误会哈,比起这个我更希望大家动手做这个项目,亲自体验将自己的程序通过定制镜像的方式跑在实机上
话说回来,既然制作 “小众虚拟机” 放在第零章,那就说明重头戏在第一章哈,且听我慢慢道来…
壹 - 把咱的虚拟机工具用 Alpine 打包器装起来
有了好用的 “小众虚拟机” 虚拟机管理工具后,咱就想心思将它做成真正的虚拟机工具系统了
先跟刚开发好 “小众虚拟机” 的 AI 协调下将整个程序打包并集成进定制 Linux 系统的路径
阅读此项目,这个项目 “小众虚拟机” 已经开发完成,我即将将其移动到定制 Linux 的 rootfs 中,你来编译前端,打包后端,在 /build 文件夹中交付可用文件,tar.gz 格式,并给出我初次配置和以后启动命令
然后就可以静待 AI 帮忙打包完所有文件并提供交付结果和交付命令了哈
当然等待期间,咱们先选型下适合装 “小众虚拟机” 及以后自行写的小程序的定制系统,在这里我会首选 Alpine
Alpine,虽然各位没怎么听说过它的大名,但是你一定用过 Docker 上的各类镜像
举个例子,你在下镜像的时候,如果没有在镜像指定系统版本(比如 :ubuntu 或者 :debian)一般下的是 Alpine 加持的镜像
Alpine 凭借其 OpenRC 简单精简的服务管理和基于 Busybox 轻量化的工具集,拥有极致小的核心体积,深得 Docker 开发者的喜爱
但是大家可能不知道的是,简单精简的 OpenRC 和 轻量化的 Busybox,在模块化系统也是数一数二的存在,非常适合制作定制系统,Alpine 官方也提供了诸如 alpine-make-vm-image 简易虚拟机打包工具供咱们制作虚拟机定制系统
不过我们的终极目标是在实机上跑咱的 小众虚拟机,那不得不上 Alpine 的另一款简易打包工具 alpine-make-rootfs 了
.1 啥是 rootfs
Linux 可能有些人没怎么真摸过,这样,想理解 rootfs 的可以在手机上下一个 MT管理器 然后一直点 .. 文件夹直到点不动为止
此时你看到的包含启动 Android 所必须的诸如 /bin /dev 等基础目录组合在一起,构成了能运行 Android 的骨架,这就算是一个根文件系统,又叫 rootfs
Linux 的哲学就是 “啥都能成目录” (Android 算是魔改版 Linux),而这些基础目录是能运行 Linux 的核心
所以我们到时候也是用 Alpine 提供的 rootfs 创建工具去创建一个能跑起来 Linux 的根文件系统
.2 怎么用上 alpine-make-rootfs
Alpine 官方建议在 Alpine 中运行 alpine-make-rootfs,我有 WSL2,不过我用的是 Debian,在另装 Alpine 速度很慢的情况下,可不可以直接在 Debian 上跑这个小工具呢?
可以的,首先把这个小工具给下下来:
Make customized Alpine Linux rootfs (base image) for containers
下好了别忘记加个执行
chmod +x alpine-make-rootfs
完成后咱就可以规划怎么安放刚做成的 “小众虚拟机” 了
正好 AI 帮忙交付好所有文件了,看一下它给的交付目录(参考用,具体看你的 AI 是怎么做的)
build/
├── README.md ← 部署说明(含下面全部命令的完整版)
├── appinn-vm-deploy.tar.gz ← 同内容的压缩包(200 KB,方便拷进 rootfs)
├── backend/ ← 后端源码(无 .venv / __pycache__ / data 运行时数据)
│ ├── app/… 35 个 .py + db/schema.sql
│ ├── requirements.txt 宽松约束(fastapi / uvicorn[standard] / pillow)
│ ├── requirements.lock.txt 精确版本(Python 3.14 实测解析出的 19 个)
│ └── run.py
├── frontend/build/ ← vite 产物 50 文件 / 328 KB
└── deploy/
├── install.sh 一次性安装(uv 建 venv + 装依赖 + 4 项自检)
├── appinn-vm.openrc OpenRC 单元(Alpine 默认)
├── appinn-vm.service systemd 单元(备用)
└── appinn-vm.env.example 环境变量样例
交付目录很清晰,然后我们把这个 tar.gz 以及 alpine-make-rootfs 拷到 WSL2 主目录中作为定制 Alpine 的核心文件
顺便建立其他文件留作备用,具体目录如下:
appinn-vm-os/
├── appinn-vm-deploy.tar.gz ← 拷过来的虚拟机工具项目
├── make-rootfs.sh ← 给 alpine-make-rootfs 调用的脚本,实现些自动化操作
└── alpine-make-rootfs ← 主角,用于打包出 rootfs
然后编辑 make-rootfs.sh 做下自动化操作,把咱们的工具打包进 rootfs
#!/bin/sh -e
# 可选,这里需要创建可调用虚拟机的用户
adduser -D -H -s /sbin/nologin appinn
adduser appinn libvirt
adduser appinn kvm
# 第一步部署项目
mkdir -p /opt/appinn-vm
tar -xzf /mnt/appinn-vm-deploy.tar.gz -C /opt/appinn-vm
cd /opt/appinn-vm
sh deploy/install.sh
chown -R appinn:appinn /opt/appinn-vm
# 第二步装 OpenRC 服务使其开机自启动
install -m 0755 deploy/appinn-vm.openrc /etc/init.d/appinn-vm
cat > /etc/conf.d/appinn-vm << 'CONFEOF'
APPINN_HOME=/opt/appinn-vm
APPINN_USER=appinn
CONFEOF
rc-update add libvirtd default
rc-update add appinn-vm default
rc-update add local default
# 可选,设置 libvirt 网络
cat > /etc/local.d/appinn-firstboot.start << 'FBEOF'
#!/bin/sh
i=0
while [ $i -lt 30 ]; do
virsh -c qemu:///system list --all >/dev/null 2>&1 && break
sleep 1
i=$((i+1))
done
virsh -c qemu:///system net-start default 2>/dev/null || true
virsh -c qemu:///system net-autostart default 2>/dev/null || true
rm -f /etc/local.d/appinn-firstboot.start
FBEOF
chmod +x /etc/local.d/appinn-firstboot.start
然后就可以让 alpine-make-rootfs 开始打包了哈
打包这茬事是真的慢(即使换源了)得留半个小时,这段时间可以做点别的事
sudo ./alpine-make-rootfs \
--mirror-uri 'https://mirrors.aliyun.com/alpine' \
--packages 'python3 py3-libvirt uv libvirt-daemon libvirt-client qemu-system-x86_64 qemu-img ovmf openrc mkinitfs linux-lts' \
--timezone 'Asia/Shanghai' \
--script-chroot \
./rootfs.tar.gz \
./build-rootfs.sh
[!note]- 一直卡在 apk not found, downloading static apk-tools
老问题了,下载国外文件慢,不过这次咱们可以不用魔法,直接自定义 alpine-make-rootfs 小工具即可
其实吧 alpine-make-rootfs 是个 shell 文件,直接拿编辑器就能打开
我们需要找到这一行,把对应的 apk.static 想方设法下载下来(用 IDM 下速度不错)
然后把 apk.static 放在 appinn-vm-os/ 目录下,并用 chmod 加执行权限
最后在编辑器找到这一行,把 : ${APK:="apk"} 改为 : ${APK:="./apk.static"} 就行了
.3 能做成 ISO 吗
当然能,接下来是本章教程比较难的部分了,闭起小嘴巴竖起小耳朵别分心
尽管咱们得到了定制系统的 rootfs,但是它只是个文件,别说实机了,放进虚拟机也是没法将其引导的
而一个真正能被启动起来的 Linux 机器,需要最起码三样东西:
rootfs 咱们有
Linux 内核咱们也有
initramfs 搭配 Linux 内核完成启动步骤,这个真没有
[!note]- 为啥 alpine-make-rootfs 小工具不在 rootfs 提供 initramfs
initramfs 的创建需要结合 rootfs 内部系统来生成,里面包含内核以及配置等,必须要咱们的定制系统亲自生成
而进入咱们的定制系统就需要解压现有的 rootfs,并以 chroot 方式进入
然后咱们就能跑一遍 initramfs 生成器也就是 mkinitfs 补全这最后一步了
所以接下来我们要改造这堆文件,将其打包成一个可以引导的 ISO 文件
先把咱刚刚生成的 rootfs 给提取出来
mkdir -p ./rootfs
sudo tar -xzf ./rootfs.tar.gz -C ./rootfs
然后我们再生成启动时必要的 initramfs,补全这最后一块定制 Alpine 的拼图
先通过 chroot 进入咱们的定制系统
sudo chroot ./rootfs
然后看一下装在咱定制系统的 Linux 内核版本号
ls /lib/modules
# 比如我的版本号是 6.6.30-0-lts
之后用 mkinitfs 将咱的 initramfs 弄出来
mkinitfs -b / -o /boot/initramfs-lts {内核版本号}
# 比如 mkinitfs -b / -o /boot/initramfs-lts 6.6.30-0-lts
生成好后检查生成的 initramfs 是否存在
ls -lh /boot/initramfs-lts
ls -lh /boot/vmlinuz-lts
如果存在那就太好了,计划完成了一大半,剩下的就是制作可引导 ISO 的流程了
中秋节出门玩了哈,未完待续…