文件归谁
改动属于容器
镜像只读层提供初始文件。容器可写层(writable layer)记录本容器新增、修改和删除的文件。这里先看没有挂载的普通路径;挂载是把另一处存储接到容器内某个路径,后面会做对照。依据:Storage。
容器里看到的是这些层合成的文件视图。新建文件进入可写层;修改镜像里的文件,也只把变化留在当前容器。删除镜像里的文件不会改写镜像,只让它在这个容器里不可见。你可以回看镜像、容器、仓库的关系。
A 和 B 来自同一镜像,都没有挂载。A 新建 /lab/note.txt 后退出。此时 B 能看到它吗?删除 A 后再从同一镜像创建 C,C 能看到吗?请分别写理由。
B 和 C 都看不到。文件只写进 A 的可写层。B 有自己的可写层,C 创建时也会得到新的一层;镜像里没有这个文件。A 退出时文件仍留在 A 内,删除 A 才删除这份变化。
深入一点:写时复制与 Docker 29 的存储后端
写时复制(copy-on-write)让容器先共享镜像文件;需要修改下层文件时,再把它复制到自己的可写层修改。删除下层文件会记录遮蔽信息,底层原件保留。具体文件布局由存储后端决定。依据:Storage drivers。
Docker Engine 29.0 起,全新安装默认用 containerd image store。它通过 snapshotter(管理文件系统快照的组件)存储镜像和容器数据;升级安装可能仍使用原有存储驱动。本页画的是文件归属,不能据此认定你的主机目录一定是 /var/lib/docker/overlay2。依据:containerd image store。
跟踪同一份变化
停止仍保留
默认情况下,停止容器只结束进程,可写层仍在。docker start 启动原容器,docker run 创建新容器。只有前者继续使用原来的可写层。依据:docker run。
- 用 run 创建 A,得到 A 自己的可写层。
- A 把 note.txt 写进可写层。先猜:进程退出后,这层还在吗?
- A 的进程退出;没有 --rm 时,容器与可写层仍保留。
- 用 start 启动 A,可以读取之前的 note.txt;读完再次退出。先猜:删除 A 后,用同一镜像能找回文件吗?
- 用 rm 删除已停止的 A,A 的可写层也被删除。
- 再次 run 创建 B,只带上镜像的初始文件;A 的变化不会进入 B。
--rm 表示容器退出时自动删除。因此,带它运行的容器即使没有手动执行 docker rm,退出后可写层也会消失。依据:Clean up。
没有挂载,也没加 --rm。A 写入文件后停止。哪一个操作会继续使用 A 的可写层?
run 会新建容器。相同镜像只保证相同的初始文件。
名字可以复用,但删除操作已经删除旧可写层。
start 启动的是现有的 A,因此保留它的文件变化。run 总会创建新容器;同名、同镜像都不会自动恢复已删除的可写层。
在你的机器上验证
删除前先查改动
编写环境没有 Docker CLI。下面给的是可复制命令与预期现象,没有实测终端输出,待维护者补测。命令在宿主机的 POSIX shell 中按顺序执行,需要能访问运行 Linux 容器的 Docker Engine。
实验可能下载 alpine:3.21 并占用本地磁盘。容器均设 --network none,不发布端口;不挂载宿主机目录。容器名 wl21-demo 必须未被占用;冲突时整组换名,不要删除已有业务容器。
① 创建文件,让进程退出
脚本第一次创建文件;若再次启动同一容器,则读取已有文件。主实验刻意不用 --rm,以便退出后检查。
docker run --name wl21-demo --network none alpine:3.21 sh -c '
mkdir -p /lab
if [ -f /lab/note.txt ]; then
cat /lab/note.txt
else
printf "first run\n"
printf "hello layer\n" > /lab/note.txt
fi
'
预期(未实测):脚本走 else 分支,打印代码中的 first run,将 hello layer 写入文件后退出。容器此时已停止。
② 用 diff 查可写层
docker diff 列出容器创建以来发生变化的文件或目录路径。它显示改动类型,不显示文件内容。依据:docker container diff。
docker diff wl21-demo
预期(未实测):关注新建的 /lab 与 /lab/note.txt,应归为新增。实际条目、顺序和额外系统路径以你的环境为准,不能把整个列表当成固定输出。
- A · Added
- 原先没有 → 新增文件或目录。
- C · Changed
- 原先存在 → 内容或元数据发生变化。
- D · Deleted
- 原先可见 → 在当前容器中被删除。
假设你手动删除一个镜像自带的普通文件,没有挂载。diff 对这个文件记录哪一个字母?
变化类型:
D 表示删除。该文件在当前容器的合成视图中不可见,镜像只读层中的原件仍然存在。新建容器仍从原始镜像开始。
③ 启动原容器,再删除
docker start -a wl21-demo
docker rm wl21-demo
预期(未实测):start -a 启动原容器并连接其输出;脚本读到原文件,打印文件里保存的 hello layer。它退出后,rm 删除容器与可写层;镜像仍在。依据:docker rm。
④ 同一镜像,新容器
docker run --rm --network none alpine:3.21 sh -c '
if [ -e /lab/note.txt ]; then
cat /lab/note.txt
else
printf "no note in new container\n"
fi
'
预期(未实测):新容器走 else 分支,打印代码中的 no note in new container。这是新的可写层。退出后,--rm 自动删除它。
深入一点:diff 是备份吗?
diff 只有改动列表,不能恢复文件,也不展示文件内的逐行差异。不要用它判断挂载数据是否已备份。若重要文件仍在旧容器里,先保留旧容器并导出需要的数据,再处理重建;不要先 rm 再找文件。
把数据的寿命延长
数据卷独立保留
数据卷(volume)是由 Docker 管理、独立于容器生命周期的存储。把它挂载到 /data 后,写入这个路径的数据进入卷,其他普通路径仍写入可写层。删除容器后,再把同一个卷挂到新容器,就能继续读取数据。依据:A volume's lifecycle。
删除 A:文件一起删除
新容器 B 的可写层从头开始。
note.txt 保留
删除 A 后,B 挂载同一卷读取。
应用同时写 /data/orders 和 /tmp/cache,只有 /data 挂载了命名卷。删除并重建容器后,怎样继续读取订单?缓存会怎样?请说出两个路径的归属。
重建时挂载同一个卷到 /data,订单仍在卷里。/tmp/cache 写在旧容器的可写层中,会随旧容器删除;新容器不会自动继承它。
- 指出要复用同一个卷
- 区分 /data 与 /tmp 的存储归属
- 说明卷不等于全容器备份
可选对照:容器自动删,命名卷保留
以下仍未实测。先确认没有名为 wl21-data 的已有卷,再执行。type=volume 指定卷,src 是卷名,dst 是容器内挂载位置。
docker volume create wl21-data
docker run --rm --network none --mount type=volume,src=wl21-data,dst=/data alpine:3.21 sh -c 'printf "hello volume\n" > /data/note.txt'
docker run --rm --network none --mount type=volume,src=wl21-data,dst=/data alpine:3.21 cat /data/note.txt
预期(未实测):第一个容器退出并被自动删除后,第二个容器仍能读到代码写入卷的 hello volume。这里使用命名卷,--rm 不会删除它;匿名卷的清理规则不同,留到下一页。
以下命令会删除本实验卷及其全部内容。确认只用于此次实验,再执行。主实验的两个容器已在前面删除。
docker volume rm wl21-data数据卷也会占用宿主机磁盘,手动删卷、应用误删、磁盘故障仍会丢数据。持久化不等于备份。下一页再比较卷、绑定挂载与内存临时挂载;本页先记住:需要跨容器保留的数据,应明确选择独立存储。
离开前检索一次
按归属判断
- 镜像给起点;容器可写层记本容器的变化。
- 停止、启动原容器会保留可写层;删除容器会删除它。
docker diff用 A / C / D 列出路径改动,不是备份。- 挂载路径里的数据归对应存储;命名卷可以跨容器复用。
旧容器把订单写到没有挂载的 /orders。你删除它后,用相同镜像、相同名字重建。哪项判断正确?
写入可写层不会修改镜像。
名字只是容器的标识,复用名字不会找回已删除的层。
删除旧容器也删除了订单所在的可写层。新建容器时再挂一个空卷,不能恢复已删除的数据。应事先把订单路径挂载到持久存储,并另做备份。
来源
核对日期:2026-11-03;说明范围:Docker Engine 29.x、Linux 容器。实验未实测,页面不记录本环境不存在的 Engine 版本或镜像大小。
- Storage · Container layer basics:只读层、可写层与挂载。
- Storage drivers · Containers and layers / Copy-on-write:文件变化与镜像层的关系。
- containerd image store:29.0 起全新安装的默认后端。
- docker run:新建容器、start 保留变化、--rm 清理规则。
- docker container diff:A / C / D 的官方定义。
- docker container rm:容器删除。
- Volumes:卷生命周期、--mount 语法、命名卷与匿名卷。