本节摘要:tmpfs 把内存伪装成容器里的目录:写入极快,容器一停全部蒸发。它适合"既要持久化语义(文件形态)、又绝不能留痕"的数据——密钥、会话、临时表、高频中间态。本节给全 --tmpfs 与 --mount 两种写法的义项、适用边界与三条安全纪律,并为伍部收尾。
别把 tmpfs 当成第四种卷:卷和绑定挂载解决"数据要留下",tmpfs 解决"数据绝不留下"。它把一块内存伪装成目录给容器用——速度是磁盘的成倍以上,生命周期与容器严格同寿。凡是"落盘即泄密、留下即负债"的数据,都该住这里。
# 简写:适合默认参数的快速挂载 docker run --tmpfs /run/secrets:rw,size=64m ... # 完整写法:可调项更多 docker run --mount type=tmpfs,dst=/app/cache,tmpfs-size=256m,tmpfs-mode=1777 ...
| 义项 | 含义 | 备注 |
|---|---|---|
| dst(或简写的路径) | 容器内的挂载点 | 必填 |
| tmpfs-size | 上限,字节或带单位 | 不给则约为宿主内存一半 |
| tmpfs-mode | 目录权限八进制 | 默认 1777 |
| rw 或 ro | 读写性 | 简写默认 rw |
$ docker run -d --name api --tmpfs /tmp/sessions:size=128m \ --tmpfs /run/secrets:ro,size=8m myapi:2.0 $ docker exec api df -h /tmp/sessions Filesystem Size Used Avail Use% Mounted on tmpfs 128M 0 128M 0% /tmp/sessions $ docker exec api sh -c 'echo token > /tmp/sessions/t1 && cat /tmp/sessions/t1' token $ docker restart api $ docker exec api cat /tmp/sessions/t1 cat: can't open '/tmp/sessions/t1': No such file or directory
三个动作演完 tmpfs 的一生:挂载点在 df 里就是一块 size 上限的内存盘;文件正常读写;容器重启后片甲不留。这个"蒸发"是特性不是缺陷——会话令牌、一次性验证码这类数据,本来就不该有来世。
三种方式放在一起,判断就清楚了:
# 同一容器三种挂载并存,各司其职 $ docker run -d --name webapp \ -v pgdata:/var/lib/postgresql/data \ -v /home/ops/app:/srv/app:ro \ --tmpfs /tmp:size=256m \ webapp:1.4
| 维度 | 命名卷 | 绑定挂载 | tmpfs |
|---|---|---|---|
| 实体 | Docker 托管目录 | 宿主机既有目录 | 内存 |
| 容器删除后 | 数据仍在 | 数据仍在 | 蒸发 |
| 宿主机可直接看 | 可以(专用目录) | 就是原目录 | 不可以 |
| 典型容量 | 磁盘大小 | 磁盘大小 | 需指定上限 |
| 典型用途 | 数据库、上传件 | 开发热改、配置 | 密钥、会话、缓存 |
选型的问句只有一个:这份数据容器没了之后要不要在? 要在,卷或绑定挂载(再按"是否要求宿主机指定位置"二选一);不在,tmpfs。把缓存放 tmpfs 还有个附带红利:高频小文件写不再磨损磁盘、也不再挤占容器可写层,容器可写层保持轻盈,2.3 的清理频率都能降下来。
⚠️ 纪律:tmpfs 的容量上限必须显式指定。不指定时默认约取宿主内存一半,应用一旦把它当日志盘狂写,宿主机内存会被迅速抽干,OOM 杀手登场时死的不止一个进程。简写语法里那个
:size=128m不是装饰。
💡 纪律:密钥文件挂 tmpfs 时顺手加只读。
--tmpfs /run/secrets:ro,size=8m——容器只需要读它,就不该有写它的能力,少一个被篡改的面。
最后一条纪律是"不要拿 tmpfs 冒充持久化做实验后忘记换回来":本地跑通的容器,配置原样上了生产,重启之后"数据没了"的事故每年都有人复刻。上生产前过一遍 run 命令的存储组选项,tmpfs 的挂载点逐个自问"这里的数据真的可以不留吗"。
tmpfs 由运行时在创建容器时挂上,属于容器配置的一部分,因此它只出现在 run(或 3.2 讲过的等价创建链)的参数里,没有独立的 tmpfs 命令族——这与 volume 命令族形成对照:卷是对象所以有命令族,tmpfs 是挂载行为所以只有选项。inspect 时它现身于 HostConfig.Tmpfs 字段:
$ docker inspect api --format '{{json .HostConfig.Tmpfs}}' {"/run/secrets":"ro,size=8m","/tmp/sessions":"size=128m"}
排错时核对这份输出,比翻部署文档可靠。
| 维度 | 命名卷 | 绑定挂载 | tmpfs |
|---|---|---|---|
| 数据位置 | Docker 托管区 | 宿主机指定目录 | 内存 |
| 容器删除后 | 仍在 | 仍在(在宿主机目录) | 消失 |
| 管理工具 | volume 命令族 | 宿主机文件工具 | 无须管理(设计如此) |
| 典型负载 | 数据库、上传文件 | 开发代码、配置证书 | 会话、密钥、高频缓存 |
| 换机迁移 | 高(导出卷即可) | 低(依赖宿主机路径) | 不适用 |
再给一组反例帮助记忆。拿 tmpfs 存上传文件:容器一重启,用户投诉"文件去哪了";拿绑定挂载存数据库:换一台路径不同的宿主机,容器起不来;拿命名卷放开发代码:改完代码容器里看不见,还得去卷的真实位置里翻。三种都是求助帖里的常客。选型出错不会当场报错,它以"看起来能跑"的方式潜伏,在某个运维动作(换机、重启、清理)之后才爆雷。本部过关自测要求你说出"反着配会出什么事",正是为此——知道错误姿势的后果,比背下正确姿势更能防事故。
数据的三种归宿(卷、绑定挂载、tmpfs)到此讲全。下一部转向容器之间怎么互相找到对方:网络部。