卷与挂载
定义
挂载(mount)是把一棵外部目录树接到工作负载 rootfs
的某个路径上。卷(volume)是由产品运行时托管的持久存储对象;使用时同样表现为一次挂载。容器可写层在实例删除后默认丢弃,因此需要跨实例保留的数据必须通过挂载进入,而不是写在
/ 的可写层里。
问题背景
镜像应当保持可替换:升级应用等于换一个镜像,而不是在旧容器的可写层里打补丁。若数据库文件、用户上传或构建缓存也写在可写层,则换镜像等于丢数据。把「代码与根文件系统」和「持久数据」分开,是容器工作流能够滚动更新的前提。
机制说明
三种最常见的形式如下。
| 形式 | 数据位于何处 | 生命周期 | 典型用途 |
|---|---|---|---|
| bind mount | 宿主上已存在的目录或文件 | 由宿主路径的所有者决定 | 开发时把源码挂进容器、注入配置文件 |
| 命名卷 | 运行时管理的目录(通常在数据根下) | 显式 volume rm 或 prune 才删除 |
数据库、需要备份的状态 |
| tmpfs | 内存 | 随容器停止而消失 | 短寿命密钥、不希望落盘的临时文件 |
bind mount
-v /home/user/app:/src 把宿主路径直接映射到容器内
/src。优点是立即可见、便于编辑;缺点是把宿主文件系统的布局与权限暴露给工作负载。路径写错或把
/ 挂进去,等于取消文件系统隔离。Box
的威胁模型因此强调:通过 bind mount 故意暴露的数据,共享内核 Sandbox
无法再保护。
命名卷
a3s-box volume create data
之后,-v data:/data 把名为 data 的卷挂到
/data。调用方不必知道宿主上的真实路径。删除 box
默认不删除卷,因此同一卷可以挂到后继实例。备份与迁移应以卷为单元,而不是以容器可写层为单元。
tmpfs
tmpfs
挂载把文件放在内存中。适合存放启动期才注入、退出后必须消失的材料。Box 在
Linux 上对 Compose 的 secret_environment 使用私有
tmpfs:把进程环境中的密钥物化到
<A3S_HOME>/runtime-secrets,只读挂载,并随 box
移除。Box 不会把该支撑降级到磁盘;宿主无法提供符合要求的 tmpfs
时,启动在资源变更前失败。
权限与所有权
挂载成功不等于进程能读写。容器内用户 ID 若与宿主文件所有者不一致,会出现「目录看见了但打不开」。User namespace 会进一步改变 ID 映射。排查时应同时检查:挂载是否存在、进程 UID、文件 mode,以及是否被标为只读。
在 Box 中的位置
- 卷子系统位于
src/runtime/src/volume/,核心类型见src/core/src/volume.rs。 - CLI 为
a3s-box volume;run/compose通过-v或 ACL / YAML 中的卷字段引用。 - Sandbox 路径上,Box 在 bundle 中声明挂载,由 OCI Runtime 完成实际
attach。MicroVM 路径上,客户机 init(
src/guest/init/)挂载 virtio-fs 与 tmpfs。 - 镜像声明的匿名卷计划在能力预检后写入初始预留,并由确切执行在 bundle 准备期间原子认领,避免靠扫描宿主目录恢复所有权。
验证命令
a3s-box volume create data |
最后一条应输出 hello。这说明数据属于卷,不属于已删除的
box。
相关与易混
- 相关:rootfs、快照、commit、diff 与 export、Compose
- 易混:
-v的左端是宿主路径时为 bind mount,是卷名时为命名卷。二者写法相近,安全含义不同。commit把可写层固化进新镜像,不能代替卷来保存数据库。