最近在Mac上装了一个anylinuxfs,方便挂载ext4文件系统的移动硬盘。
第一次运行的时候,会先拉取alpine的docker镜像,可是它似乎只会从官方的镜像源拉取,这对于国内用户不太方便。因此,我就尝试着寻找手动从国内的docker镜像站拉取镜像的方法。
首先,在运行的时候可以看到“Initializing VM root filesystem”这样的输出,直接在源码里面找这样的字符串,发现是在anylinuxfs/src/vm_image.rs的init_rootfs()下。
继续往下看,会发现它是调用另一个程序来初始化:
let mut init_rootfs_cmd = Command::new(&config.paths.init_rootfs_path);
这个init_rootfs_path的值可以在anylinuxfs/src/main.rs的load_config()中找到,即libexec/init-rootfs。
到anylinuxfs所在目录下找,可以找到这个对应的程序:/opt/homebrew/Cellar/anylinuxfs/0.16.2/libexec/init-rootfs
接下来是运行参数:
init_rootfs_cmd.args(&[
"-n",
&dns_server,
"-docker-ref",
docker_ref,
"-base-dir",
&effective_base_dir,
]);
其中,-n就是DNS服务器地址,不难理解。-docker-ref就是镜像名称,默认为alpine:latest。-base-dir就是rootfs存放的地址,尽管之前anylinuxfs没能成功拉取镜像,但是它在~/.anylinuxfs下有创建一个alpine目录,因此这里的值显然就是alpine。
由于需要使用国内的镜像源,因此-docker-ref的值需要在此基础上加上镜像源的url,例如mirror.site/library/alpine:latest。
现在得到了完整的运行命令,像这样:
init-rootfs -n 114.114.114.114 -docker-ref mirror.site/library/alpine:latest -base-dir alpine
尝试运行,果然能够正常拉取下来了。
成功拉取之后,接下来还要判断,需要满足什么样的条件才不会重新初始化。回到vm_image.rs的init_rootfs(),可以看到它的判断方式:检查alpine文件系统下必要的文件是否存在、fstab是否已经配置好、版本是否相同。
观察alpine的文件系统,发现前两个条件已经满足,现在剩下最后一个条件,对比版本:
rootfs_version_matches(&root_ver_file_path, ROOTFS_CURRENT_VERSION)
本质上,就是对比两个rootfs.ver文件的内容。其中,ROOTFS_CURRENT_VERSION所在的rootfs.ver位于/opt/homebrew/Cellar/anylinuxfs/0.16.2/share/alpine下,在我这个版本中,它的值为1.4.1。root_ver_file_path就是~/.anylinuxfs/alpine/rootfs.ver,前面运行init-rootfs的时候并不会创建这个文件,因为创建rootfs.ver这一步是在init_rootfs下进行的。
创建好这个rootfs.ver并将其内容同样设为1.4.1,再次运行anylinuxfs mount,现在可以直接使用现有的alpine,而不需要重新初始化了。