金华市网站建设_网站建设公司_Banner设计_seo优化
2026/1/1 0:26:39 网站建设 项目流程

1 需求描述

  • 个人服务器的磁盘空间不足了,恍然发现主要是 docker 占用了太多空间。那么如何安全地清理Docker服务占用的磁盘空间呢?

2 解决方案

检查磁盘空间情况

  • 检查磁盘空间,确认overlay2占用的空间
# df -h
Filesystem      Size  Used Avail Use% Mounted on
udev            7.9G     0  7.9G   0% /dev
tmpfs           1.6G  2.1M  1.6G   1% /run
/dev/sda1       197G   59G  131G  32% /
tmpfs           7.9G     0  7.9G   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
/dev/sda15      124M   12M  113M  10% /boot/efi
overlay         197G   59G  131G  32% /var/lib/docker/overlay2/3ea43957615f592f2a7b28512fd7f344ac762bfc80a4a964ac467b17f562203e/merged
overlay         197G   59G  131G  32% /var/lib/docker/overlay2/bd8702eb9dcc24aff1a54387374f6609b431aabb1c7131359296867986dc84a0/merged
overlay         197G   59G  131G  32% /var/lib/docker/overlay2/b6b66bb24dc1186c12f18ddb3487a3b81ef40767993a722b08359808635461bd/merged
overlay         197G   59G  131G  32% /var/lib/docker/overlay2/0bf724bd62f24f7411c573b03fef2816c0b14a696ce04e8b78c4616b704b1b86/merged
overlay         197G   59G  131G  32% /var/lib/docker/overlay2/d7caeb11110a19f032d90855ae491c9cb35c5cbbd57daf266e5b12c3494ba21e/merged
overlay         197G   59G  131G  32% /var/lib/docker/overlay2/e4ec25032cb6814980100348c68e937bb4b9e48c098dbf99c5a543428f73e8b7/merged
overlay         197G   59G  131G  32% /var/lib/docker/overlay2/53277c320141d4efa122ad91fe38fe9e7362d29d2cdabb5c3d8c2a1bdea12120/merged
overlay         197G   59G  131G  32% /var/lib/docker/overlay2/b5b65a3ebe16e33091590dbdbea7c51b6ffc8ab894358d9cb7d95934a14a8579/merged
overlay         197G   59G  131G  32% /var/lib/docker/overlay2/864d8e14ba8c74bc627a35847aff844e45acc43686abc7d81c471969fe2b8386/merged
overlay         197G   59G  131G  32% /var/lib/docker/overlay2/5d0d903a3ccd4b5b2cd6741d4eb9654b10667fd5707c13d3d51f2678b5c4d7a2/merged
overlay         197G   59G  131G  32% /var/lib/docker/overlay2/4c2bf66ffcd7f2a8bb03dcee3f5d445c4be9c56b899aaea319689a92193fbaf4/merged
overlay         197G   59G  131G  32% /var/lib/docker/overlay2/3a9e03fd9038307f133da2800527610a6334e458d42d8a406ea30e108dd8ec58/merged
overlay         197G   59G  131G  32% /var/lib/docker/overlay2/4c509ec79872340afca9c9a763782005fa043f5e4c988acc9f24f371d7c79b5c/merged
overlay         197G   59G  131G  32% /var/lib/docker/overlay2/d9bad19c0ce3f9ff18364ee882e52bb9fef3db1c5a99bdbfb97fe4dbbea6f985/merged
overlay         197G   59G  131G  32% /var/lib/docker/overlay2/492549dc47bc8b55a73c945ad3eb699fe34c5e563d22cf4b16383048420fbffe/merged
overlay         197G   59G  131G  32% /var/lib/docker/overlay2/31a7a2393fa100d485b852cda049e4efe7e2d57240a638bde911901a9878e6bd/merged
overlay         197G   59G  131G  32% /var/lib/docker/overlay2/c56e33e03da1a8e849eb8d02a660cfdbf1b21774a99adb8bb1435e072ead0eaf/merged
tmpfs           1.6G     0  1.6G   0% /run/user/0# cd /var/lib/docker/overlay2
# du --max-depth=1 -ah ./
...
3.9G	./cbd00072f337eac535231f5070dd185eb5396a2a38f503a180d85f4c3dfd56dc
52K	./492f6bb1fa6939b3b4c9bde42c488e821e39dc284a506a69009232666b3b646e
24K	./4ac719b443482d3094f55f87465fd0a2e055e03d8884aab104c9a9b749b6a888
311M	./98f0e8fe08003084033830be8d14843ab31751dd66abec2a859e1123bd4264cf
4.1M	./d569993160caa256ff9578a2e2c88a809eb94cbdb19b42bcf789ade5e3ede6f2
6.8M	./40cfa823fdcda9ddd582bc3ae8c2e2409f53c2484488b919dd0c90b35759500e
56K	./ff0d25275d523771576a3e7ef0249fbcf88e7b94ca0f2e4bc806a2bbcf1391be
28K	./c04b54aa554e1a1c82ba1d3af8effefd02d4f1aa2b246b6f863e6643fad56fb8
4.1G	./2e645b5187bc64ae8bcd1eb93c70343c68bd94c610681b37faf486b4015eb62e
...
786M	./c195dcf2dc6fc330b450cfdf76066d661bbd9c8c306e68de8c183c9786ee82d8

如果看到 overlay Use% 这一栏占用百分比过高,说明确实是dockeroverlay目录占用过高导致服务器磁盘空间过小的问题

检查容器的占用情况

  • 检查docker 各模块(镜像、容器、本地卷、缓存)中的占用情况
# docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          20        18        8.739GB   684.5MB (7%)
Containers      18        17        11.12MB   6.23kB (0%)
Local Volumes   7         6         348.8MB   72.39MB (20%)
Build Cache     754       0         40.38GB   40.38GB
  • 行说明
  • Images: 镜像的数量及占用大小
  • Containers: 容器的数量及占用大小
  • Local Volumes: 本地卷数量及占用大小
  • Build Cache: 打包构建时的缓存大小

我们主要是清理ImagesContainersBuild Cache中的文件

  • 列说明
  • RECLAIMABLE 列:英译"可收回的;可教化的",此处指的是“未使用”的镜像或镜像占用的空间(意思是:没有基于这些镜像运行的容器)。
这是您可以删除而不会破坏任何内容的镜像总大小。
这正是为什么如果您运行docker system prune -a或docker image prune -a,Docker 会删除它们。
-a 告诉 Docker 删除所有未使用的镜像,没有它,Docker 只会删除悬挂(未标记)的镜像。

执行清理操作

清理无用的Images

  • 先查看一下目前存在的镜像
docker images

结果

REPOSITORY                                     TAG       IMAGE ID       CREATED        SIZE
<none>                                         <none>    defd79220cd6   2 months ago   239MB

可以看到有很多到<none>字样的镜像。这里我只截取一个作为参考。发现数量和占用大小都挺多的。
none镜像被官方称为dangling镜像————代表没有标签且没有被使用过的镜像,可以安全放心的清理。

  • 清理方法也很简单,执行下面命令:
docker image prune

这条命令会自动帮我们清除带有<none>无效镜像
命令执行完毕会提示释放了多少个空间。
然后,我们再来执行docker images命令会发现带有<none>的镜像全部被清理干净了磁盘空间也得到了释放!

清理Containers容器中的日志

  • Containers容器占用最多的基本上就是日志文件
  • Docker 日志(也就是 docker logs 输出的东西) 默认存放在:

这个日志文件可能会越积越大,需要定期清理

/var/lib/docker/containers/<container-id>/<container-id>-json.log

例如:

[root@xxx yy]# docker ps 
CONTAINER ID   IMAGE                       COMMAND                  CREATED         STATUS                            PORTS                                                    675c9b2dcccd   nginx:1.24.0                "/docker-entrypoint.…"   9 months ago    Up 54 minutes                     0.0.0.0:80-81->80-81/tcp, 0.0.0.0:443->443/tcp           nginx[root@xxx yy]# ls -la /var/lib/docker/containers/675c9b2dcccd648a2f36f70348cc0c2c43cc3de80a51b0ac47215b5044175f42/
total 35744
drwx--x--- 4 root root     4096 Dec 31 23:19 .
drwx--x--- 7 root root     4096 Sep 19 23:22 ..
-rw-r----- 1 root root 36556073 Dec 31 23:37 675c9b2dcccd648a2f36f70348cc0c2c43cc3de80a51b0ac47215b5044175f42-json.log
drwx------ 2 root root     4096 Mar 23  2025 checkpoints
-rw------- 1 root root     3821 Dec 31 23:19 config.v2.json
-rw------- 1 root root     1740 Dec 31 23:19 hostconfig.json
-rw-r--r-- 1 root root       13 Dec 31 23:19 hostname
-rw-r--r-- 1 root root      206 Dec 31 23:19 hosts
drwx--x--- 2 root root     4096 Mar 23  2025 mounts
-rw-r--r-- 1 root root      306 Dec 31 23:19 resolv.conf
-rw-r--r-- 1 root root       71 Dec 31 23:19 resolv.conf.hash
  • 从根源限制Docker日志大小(一劳永逸的方法 推荐)

我们可以设置限制日志大小从而不用每次都来手动删除日志

vim /etc/docker/daemon.json  //编辑内容:{"log-driver": "json-file","log-opts": {"max-size": "10m","max-file": "3"}
}

这样,每个容器最多只会占用30MB的日志空间。
写入完成后并不会立刻生效,需要重启运行中的容器。
如果有条件的情况下,建议重启docker会对所有容器都生效:

systemctl restart docker
  • 解决方法1:
  • 先找到日志文件路径:
docker inspect <容器名或ID> --format='{{.LogPath}}'
  • 然后清空它
truncate -s 0 "$(docker inspect <容器名或ID> --format='{{.LogPath}}')"
  • 解决方法2: 还有另一种方式可以一次性清理所有容器
find /var/lib/docker/containers/ -name "*-json.log" -exec truncate -s 0 {} \;

不删除文件、不重启服务,不影响任何容器运行

清理构建缓存(Clear Build Cache)

  • Build Cache主要是构建时的缓存,清理它们下次打包构建时速度可能会慢点,对于系统没有任何影响。

如果磁盘占用过高需要及时清理。清理方法也特别简单就一行命令

docker builder prune

执行完成后,可以发现服务器的内存又可以释放一截。

3 Docker 服务的文件目录体系

/var/lib/docker/overlay2

Docker Overlay2 : 基于内核的图层存储驱动程序

  • DockerOverlay2存储驱动程序】是一个基于内核的图层存储驱动程序,用于创建和管理 Docker 容器。
  • 它通过将多个【只读层】叠加到单个【可写层】来实现这一功能,这使得 Docker 可以高效地共享复用【镜像层】,从而减小了【镜像大小】并加速了【容器的启动速度】。
  • /var/lib/docker/overlay2Overlay2 存储驱动程序的【默认存储目录】,用于保存 Docker 【容器镜像】和【容器数据】。这个目录的结构和用途如下:
  • lower 目录:这个目录包含了所有基础镜像层,它们是只读的并且被叠加在一起。每个基础镜像层都有一个对应的子目录,例如“sha256:c77159850506976d0a9b83b21155b51d88e49c72b1f09493e80d8c664f44a4c41”。
  • upper 目录:这个目录包含了所有叠加的读写层,它们位于基础镜像层之上。这些读写层通常包含容器的修改和新增内容,例如容器的配置文件、日志等。
  • merged 目录:这个目录包含了最终的容器镜像,它是所有叠加层内容的聚合。Docker 使用这个目录来提供容器运行时所需要的文件系统视图。
  • diff 目录:这个目录包含了叠加层的差异内容,即哪些文件或目录在叠加过程中发生了变化。这些差异内容对于 Docker 的备份和迁移操作非常有用。
  • Overlay2 驱动程序使用了基于 inode存储模型,它将不同的【图层】都挂载到【相同的文件系统目录】下,同时使用不同的【命名空间】来进行隔离。

这种设计使得 Overlay2 能够高效地管理【容器】、【镜像】和【数据】,并且能够实现快速的【数据恢复】和【备份】。
在实际应用中,/var/lib/docker/overlay2 目录的大小可能会随着容器的数量和大小而增长。
如果服务器磁盘空间不足,可能会导致容器无法正常启动或运行。因此,定期监控和管理 /var/lib/docker/overlay2 目录的大小是非常重要的。
在管理 /var/lib/docker/overlay2 目录时,可以通过删除不必要的容器清理旧的镜像层增加磁盘空间等方法来减小其大小。
另外,也可以考虑使用 Docker 的磁盘清理工具第三方工具来帮助管理 Docker 存储空间。

用生活类比理解 overlay2 的本质

想象你有一叠透明的画画纸:

  • 最下面一张是「基础画纸」(相当于 Docker 镜像),上面画着固定的图案(程序和系统文件)。
  • 每次在上面盖一张新的「透明纸」(相当于容器的层),你可以在新纸上修改或添加图案,不会破坏下面的纸。
  • overlay2 就是管理这叠纸的「文件夹」,让所有纸看起来像一张完整的画(容器运行时的文件系统)。

overlay2 的核心组成部分及作用

  • 目录结构总览
/var/lib/docker/overlay2/
├── l   # 软链接文件夹,指向具体层的路径
├── mnt # 容器挂载点,合并所有层的文件
├── <hash1>/ # 镜像层(只读)
│   ├── diff/ # 存储该层的文件变更
│   ├── link # 层的唯一标识
│   └── lower # 记录下层的路径
└── <hash2>/ # 容器层(可写)├── diff/ # 存储容器运行时的修改├── link # 层的唯一标识├── lower # 记录所有下层镜像的路径└── work # 临时工作目录,用于文件修改
  • 关键部分详解
  • 镜像层(只读层):

像图书馆的书,多个容器可以共享同一本书(镜像层),节省空间。

  • 容器层(可写层):

像在书上贴便签,容器运行时的修改(如新建文件、修改内容)都存在这里,不影响原书。

  • mnt 目录

像「魔法桌面」,把所有层的文件合并显示,容器看到的就是这个合并后的文件系统

例如:

(base) [root@xxxxx halo]# ls -la /var/lib/docker/overlay2/98f0e8fe08003084033830be8d14843ab31751dd66abec2a859e1123bd4264cf
total 52
drwx--x---   4 root root  4096 Feb 15  2025 .
drwx--x--- 160 root root 28672 Dec 31 23:07 ..
drwxr-xr-x   8 root root  4096 Feb 15  2025 diff
-rw-r--r--   1 root root    26 Feb 15  2025 link
-rw-r--r--   1 root root   260 Feb 15  2025 lower
drwx------   2 root root  4096 Feb 15  2025 work

overlay2 背后的工作原理

┌──────────────────────────────────────────────────────────┐
│ 当启动容器时,overlay2 做了这些事:                        │
├───────────────────┬──────────────────────────────────────┤
│ 1. 找到镜像的所有只读层(如 A、B、C 层)                  │
│   ▼                                                          │
│ 2. 创建一个新的可写层 D,用于存储容器的修改                │
│   ▼                                                          │
│ 3. 在 mnt 目录中,用「联合文件系统」把 A+B+C+D 合并成一个  │
│   ▼                                                          │
│ 4. 容器访问的就是这个合并后的文件系统,修改会存在 D 层      │
└──────────────────────────────────────────────────────────┘
  • 联合文件系统原理:

就像叠透明纸,下面的层(镜像)是只读的,上面的层(容器)可以修改。当修改一个文件时:

  • 先把原文件从下层「复制」到上层(称为「写时复制」)
  • 在上层修改这个复制后的文件,下层文件保持不变

使用场景

  1. 多个容器共享同一镜像

场景:运行 10 个 Nginx 容器,每个容器共享同一个 Nginx 镜像层,只需要存储一次镜像文件。
好处:节省磁盘空间,像 10 个人看同一本漫画书,不用每人买一本。

  1. 容器快速创建和删除

场景:测试环境中频繁创建、删除容器(如 CI/CD 部署)。
原理:删除容器只需要删除可写层,镜像层不受影响,像撕掉便签,书还在。

  1. 数据持久化

场景:容器中数据库的数据需要保存,即使容器删除也不丢失。
做法:把数据目录挂载到宿主机(绕过 overlay2 的层机制),像把重要的便签单独贴在书桌抽屉里。

底层技术关键点(用代码比喻)

  • 虽然 overlay2 是用 C 语言写的,但可以用 PHP 逻辑理解核心思想:
// 模拟 overlay2 的核心逻辑(非实际代码,仅用于理解)
class Overlay2 {// 存储所有层的信息private $layers = [];// 添加一个镜像层(只读)public function addImageLayer($layerHash, $parentLayers) {$this->layers[$layerHash] = ['type' => 'read-only', // 标记为只读'parent' => $parentLayers, // 记录下层是谁'path' => "/var/lib/docker/overlay2/$layerHash/diff" // 层的文件路径];echo "创建镜像层 {$layerHash},像添加一本新漫画书\n";}// 创建容器的可写层public function createContainerLayer($containerId, $imageLayers) {$layerHash = md5(uniqid()); // 生成唯一标识$this->layers[$layerHash] = ['type' => 'read-write', // 标记为可写'parent' => $imageLayers, // 下层是所有镜像层'path' => "/var/lib/docker/overlay2/$layerHash/diff",'work_path' => "/var/lib/docker/overlay2/$layerHash/work" // 临时工作目录];// 创建软链接,方便快速找到层symlink($this->layers[$layerHash]['path'], "/var/lib/docker/overlay2/l/$containerId");echo "为容器 {$containerId} 创建可写层 {$layerHash},像准备一张空白便签\n";}// 合并所有层,生成容器看到的文件系统public function mountContainer($containerId, $mountPath) {// 获取所有下层(镜像层)的路径$lowerPaths = [];foreach ($this->layers as $hash => $layer) {if (in_array($hash, $this->layers[$containerId]['parent'])) {$lowerPaths[] = "lowerdir={$layer['path']}";}}// 添加当前可写层的路径$lowerPaths[] = "upperdir={$this->layers[$containerId]['path']}";$lowerPaths[] = "workdir={$this->layers[$containerId]['work_path']}";// 用联合文件系统挂载(实际是调用 Linux 的 mount 命令)$command = "mount -t overlay overlay -o " . implode(',', $lowerPaths) . " $mountPath";exec($command);echo "把所有层合并到 {$mountPath},像把所有透明纸叠在一起\n";}// 当容器修改文件时(写时复制)public function modifyFile($containerId, $filePath) {$layer = $this->layers[$containerId];$sourceLayer = $this->findFileSourceLayer($filePath, $layer['parent']);if ($sourceLayer) {// 从下层复制文件到当前可写层$sourceFile = "{$sourceLayer['path']}/" . substr($filePath, 1);$targetFile = "{$layer['path']}/" . substr($filePath, 1);copy($sourceFile, $targetFile);echo "从下层复制文件到可写层,像把书上的内容抄到便签\n";} else {// 文件是新建的,直接存在可写层touch($targetFile);echo "新建文件,存在便签上\n";}}// 查找文件在哪个下层private function findFileSourceLayer($filePath, $parentHashes) {foreach ($parentHashes as $hash) {$layerPath = "{$this->layers[$hash]['path']}/" . substr($filePath, 1);if (file_exists($layerPath)) {return $this->layers[$hash];}}return false;}
}

思维导图:overlay2 的全貌

/var/lib/docker/overlay2 的世界
├── 核心作用:管理容器和镜像的文件层,像叠透明纸
├── 组成部分:
│   ├── 镜像层(只读):多个容器共享的「基础画纸」
│   ├── 容器层(可写):每个容器独有的「便签纸」
│   ├── mnt 目录:合并所有层的「魔法桌面」
│   └── work 目录:临时修改文件的「草稿本」
├── 工作原理:
│   ├── 联合文件系统:把多层文件合并显示
│   ├── 写时复制:修改时先复制到可写层,不影响下层
│   └── 软链接:快速找到层的路径,像书签
├── 使用场景:
│   ├── 多容器共享镜像:节省空间,像多人看同一本书
│   ├── 快速创建容器:只加便签,不复制整本书
│   └── 数据持久化:重要数据单独存,不放在便签上
└── 底层技术:├── Linux 内核的 overlay 或 overlay2 驱动├── mount 命令实现文件系统挂载└── 写时复制(Copy-on-Write)机制

总结:透过现象看本质

overlay2 就像一个「文件层管理员」,它的核心魔法是:

  1. 用「透明纸叠放」的方式管理镜像和容器的文件,让它们共享底层资源又互不干扰;
  2. 当你修改文件时,它偷偷把修改内容放到最上面的「便签纸」上,不破坏下面的「原书」;
  3. 最终呈现给容器的,是所有纸叠在一起的「完整画面」,但实际存储的是每一层的差异,节省了大量空间。

/var/lib/docker/containers/<container-id>/<container-id>-json.log

需求参见:本文的第2章 清理容器的日志

Y 推荐文献

  • [Docker] Docker 基础教程(概念/原理/基础操作) - 博客园/千千寰宇
  • [Linux]常用命令之【du/fdisk/df/ls】#磁盘管理/文件管理# - 博客园/千千寰宇
  • /var/lib/docker/overlay2到底是干什么的? - CSDN

X 参考文献

  • Docker中overlay2磁盘占用爆满清理方案 - segmentfault.com
  • 在docker system df中显示的“RECLAIMABLE”空间是什么? - dev59.com
  • 深入了解容器 overlay 文件系统和 /var/lib/docker/overlay2 下的目录作用 - 腾讯云
  • /var/lib/docker/overlay2 占用很大,清理Docker占用的磁盘空间,迁移 /var/lib/docker 目录... - 阿里云

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询