揭开 Overlay2 的写时复制真相
在容器化运维的日常中,我们常遇到一个令人困惑的现象:明明在容器内删除了大量日志或临时文件,宿主机上的磁盘占用却纹丝不动,甚至随着镜像提交(commit)操作不降反升。这并非存储系统出现了 Bug,而是 Docker 底层采用的 Overlay2 驱动在“写时复制”(Copy-on-Write, CoW)机制下的正常表现。理解这一机制,是避免生产环境存储爆炸、优化镜像体积的关键。
Overlay2 作为目前 Docker 默认的存储驱动,其核心逻辑在于将多个目录叠加为一个统一的文件系统视图。它由下层的只读镜像层(LowerDir)和上层的可写容器层(UpperDir)组成。当容器启动时,这两个目录通过内核模块合并为_merged 目录,供容器进程访问。这种设计极大地节省了空间,因为多个容器可以共享相同的底层只读数据。然而,这种共享也带来了数据修改的特殊性:任何对文件的写入、修改或删除,都不会直接作用于底层的只读层,而是全部发生在顶部的可写层。
删除文件为何反而占用空间?
很多开发者 intuitively 认为,在容器中执行rm命令删除一个大文件,应该能立即释放磁盘空间。但在 Overlay2 的架构下,事实恰恰相反。当你删除一个源自只读镜像层的文件时,Docker 无法真正移除底层的数据(因为那是只读的,且可能被其他容器共享)。为了在合并视图中“隐藏”这个文件,Overlay2 会在可写层(UpperDir)创建一个特殊的标记文件,称为whiteout(通常以.wh.开头)。
这个 whiteout 标记的作用类似于一个“遮挡板”,告诉联合文件系统:“虽然下层有这个文件,但在上层视图中请忽略它。”这意味着,原本占据空间的实体文件虽然在下层依然存在,而在上层却新增了一个标记文件。如果你此时执行docker commit将当前容器状态保存为新镜像,这个 whiteout 标记会被固化到新镜像的层中。结果是,你的新镜像不仅没有变小,反而因为包含了这些删除标记而变得更大。这就是为什么频繁在容器内安装软件后又卸载,会导致镜像层层膨胀的根本原因。
实战:用 tree 命令透视 diff 目录
要直观地验证上述理论,我们可以深入宿主机的/var/lib/docker/overlay2目录进行观察。假设我们有一个正在运行的 Nginx 容器,首先通过docker inspect获取其对应的 UpperDir 和 LowerDir 路径。
进入该容器的 UpperDir 目录(即 diff 目录),这里记录了容器运行以来的所有变更。在未做任何操作前,该目录可能为空或仅有少量初始化文件。此时,我们在容器内创建一个测试文件test.log并写入数据,随后再将其删除。回到宿主机的 UpperDir 目录,使用tree命令查看结构:
# 在宿主机上执行,查看容器可写层的变化 tree /var/lib/docker/overlay2/<container_id>/diff你会发现,即使文件已被删除,diff目录下依然会出现一个名为.wh.test.log的文件。这个以.wh.为前缀的文件就是前述的 whiteout 标记。它明确证明了删除操作并没有释放底层空间,而是在上层留下了“痕迹”。如果此时对该容器执行 commit 操作,这个 whiteout 文件将成为新镜像层的一部分,永久占用存储空间。
此外,通过tree -L 2查看整个 overlay2 的层级结构,还能清晰看到lower文件中的链表关系,它指示了当前层依赖了哪些下层 ID。每一层都独立记录着自己的 diff 变化,层层叠加,构成了最终的文件系统视图。
优化策略与卷挂载的误区
面对这种机制,运维开发者应采取更科学的镜像管理策略。首先,严禁在生产流程中依赖docker commit来保存变更。正确的做法是使用Dockerfile进行构建,将安装、配置、清理操作合并在同一个RUN指令中。例如,使用&&连接安装与清理命令,确保在同一层内完成软件的下载、安装与缓存清理,这样生成的层只包含最终必要文件,而不会产生中间层的冗余或 whiteout 标记。
其次,需要严格区分镜像层数据与持久化数据。Docker 的卷(Volume)机制基于 bind mount 实现,其数据直接存储在宿主机的特定目录(如/var/lib/docker/volumes)或指定路径下,完全独立于 Overlay2 的联合文件系统。这意味着,无论你在容器内如何删除文件,只要数据写在挂载的卷中,就不会触发 CoW 机制,也不会产生 whiteout 标记。更重要的是,执行docker commit时,默认会排除所有挂载卷中的数据。这一设计初衷是为了保证镜像的纯净性与可移植性,避免将特定环境的运行时数据打包进镜像。
因此,若发现存储异常增长,应优先检查是否误将大量动态数据写入了容器层而非卷中,或者是否存在频繁的 commit 操作固化了删除标记。定期清理未使用的悬空镜像(dangling images),并结合构建时的多层优化,才是控制 Docker 存储体积的正道。理解 Overlay2 的叠加逻辑,不仅能帮助我们排查存储问题,更能让我们在设计容器架构时,做出更符合底层原理的决策。
网络安全的知识多而杂,怎么科学合理安排?
下面给大家总结了一套适用于网安零基础的学习路线,应届生和转行人员都适用,学完保底6k!就算你底子差,如果能趁着网安良好的发展势头不断学习,日后跳槽大厂、拿到百万年薪也不是不可能!
初级黑客
1、网络安全理论知识(2天)
①了解行业相关背景,前景,确定发展方向。
②学习网络安全相关法律法规。
③网络安全运营的概念。
④等保简介、等保规定、流程和规范。(非常重要)
2、渗透测试基础(一周)
①渗透测试 的流程、分类、标准
②信息收集技术:主动/被动信息搜集、Nmap工具、Google Hacking
③漏洞扫描、漏洞利用、原理,利用方法、工具(MSF)、绕过IDS和反病毒侦察
④主机攻防演练:MS17-010、MS08-067、MS10-046、MS12-20等
3、操作系统基础(一周)
①Windows系统常见功能和命令
②Kali Linux系统常见功能和命令
③操作系统安全(系统入侵排查/系统加固基础)
4、计算机网络基础(一周)
①计算机网络基础、协议和架构
②网络通信原理、OSI模型、数据转发流程
③常见协议解析(HTTP、TCP/IP、ARP等)
④网络攻击技术与网络安全防御技术
⑤Web漏洞原理与防御:主动/被动攻击、DDOS攻击、CVE漏洞复现
5、数据库基础操作(2天)
①数据库基础
②SQL语言基础
③数据库安全加固
6、Web渗透(1周)
①HTML、CSS和JavaScript简介
②OWASP Top10
③Web漏洞扫描工具
④Web渗透工具:Nmap、BurpSuite、SQLMap、其他(菜刀、漏扫等)
想要入坑黑客&网络安全的朋友,给大家准备了一份:282G全网最全的网络安全资料包免费领取
网络安全学习路线&学习资源
网络安全工程师企业级学习路线
很多小伙伴想要一窥网络安全整个体系,这里我分享一份打磨了4年,已经成功修改到4.0版本的《平均薪资40w的网络安全工程师学习路线图》对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
如图片过大被平台压缩导致看不清的话,大家记得点个关注,关注之后系统后台会自动发送给大家!到时候记得看后台消息就行了。
学习资料工具包压箱底的好资料,全面地介绍网络安全的基础理论,包括逆向、八层网络防御、汇编语言、白帽子web安全、密码学、网络安全协议等,将基础理论和主流工具的应用实践紧密结合,有利于读者理解各种主流工具背后的实现机制。
网络安全源码合集+工具包
视频教程
视频配套资料&国内外网安书籍、文档&工具
网络安全学习路线&学习资源