清理 Docker/overlay2 目录是否安全?

367

我在AWS EC2上运行了一些 Docker 容器,但是 /var/lib/docker/overlay2 文件夹的磁盘空间占用增长得非常快。

我想知道是否安全删除其内容?或者 Docker 是否有一些命令可以释放一些磁盘空间。


更新:

我已经尝试过docker system prune -a,但是它只回收了 0KB 的空间。

此外,我的 /docker/overlay2 磁盘大小要比 docker system df 命令输出的结果大得多。

阅读了 Docker 文档和 BMitch 的答案后,我认为触碰这个文件夹是一个愚蠢的想法,我将尝试其他方法来释放我的磁盘空间。


5
你有没有找到这个问题的答案?我仍然遇到同样的问题。 - Saurabh_Jhingan
22
我运行了 docker image prune --alldocker system prune -a 命令。这使我的磁盘空间回收了约50GB,原本这些文件存放在 /var/lib/docker/overlay2 目录下。但是,仅运行 docker system prune -a 命令就足够了。另外,我的配置信息如下:操作系统:Ubuntu 20Docker版本:19.03.12 - Binita Bharati
1
修剪没帮到我,尝试这个命令代替:docker volume rm $(docker volume ls -qf dangling=true) 更多信息请参考此链接:https://dev59.com/tVYN5IYBdhLWcg3w7MC5#75928154 - lambodar
3
如果你不确定docker system prune -a是否真的能清除所有东西,你可以运行以下命令来查找被Docker忽略的文件夹。find /var/lib/docker/overlay2 -mindepth 1 -maxdepth 1 -type d \! -exec bash -c "docker ps -q | xargs docker inspect --format '{{.GraphDriver.Data}}'| grep -q "{} \; -print请注意,这将识别出任何在正在运行的Docker镜像的GraphDriver中未提及的文件夹。你应该会找到一个名为l的文件夹,其中包含了指向其他所有文件夹的链接列表。 - Tobi Oetiker
根据@TobiOetiker的评论,我冒险手动删除了find命令的输出(首先完全停止了Docker),除了“l”文件夹。到目前为止,它重新启动并正常运行,并且我恢复了大约30GB的磁盘空间。 - undefined
24个回答

332
Docker使用/var/lib/docker存储镜像、容器和本地命名卷。删除此内容可能导致数据丢失并可能停止引擎运行。特别是overlay2子目录包含了镜像和容器的各种文件系统层
要清理未使用的容器和镜像,请参见docker system prune。还有一些选项可以删除卷甚至已标记的镜像,但默认情况下它们不启用,因为可能会导致数据丢失。
$ docker system prune --help

Usage:  docker system prune [OPTIONS]

Remove unused data

Options:
  -a, --all             Remove all unused images not just dangling ones
      --filter filter   Provide filter values (e.g. 'label=<key>=<value>')
  -f, --force           Do not prompt for confirmation
      --volumes         Prune volumes

梅干永远不会删除以下内容:

  • 正在运行的容器(使用docker ps列出它们)
  • 这些容器上的日志(有关限制日志大小的详细信息,请参见此帖子
  • 由这些容器进行的文件系统更改(可通过docker diff查看)

此外,任何在正常docker文件夹之外创建的内容可能无法在此垃圾回收期间被docker看到。这可能来自其他应用程序向此目录写入,或者是docker引擎的先前配置(例如从AUFS切换到overlay2,或者在启用用户命名空间后可能发生)。

如果忽略此建议并删除类似于overlay2的单个文件夹,会发生什么?容器文件系统是从一组文件系统层组装而成的,overlay2文件夹是docker执行某些挂载的地方(当容器正在运行时,您将在mount的输出中看到它们)。在使用时删除其中一些内容将从正在运行的容器中删除文件系统的某些块,并可能破坏从受影响镜像启动新容器的能力。请参见此问题以了解可能的结果之一。


为了完全刷新Docker到一个干净的状态,您可以删除整个目录,而不仅仅是像overlay2这样的子目录

# danger, read the entire text around this code before running
# you will lose data
sudo -s
systemctl stop docker
rm -rf /var/lib/docker
systemctl start docker
exit

引擎将以完全空的状态重新启动,这意味着您将丢失以下所有内容:

  • 图像
  • 容器
  • 命名卷
  • 用户创建的网络
  • 集群状态

3
overlay2文件夹应包含所需的文件系统层以用于您的镜像和容器。您可以忽略此建议,但是如果您在操作时破坏了文件系统并需要恢复失败的系统,请不要向我寻求建议,特别是因为我已经提供了支持的方法来清理您的文件系统。 - BMitch
71
我尝试了 docker system prune -a,但回收了0kb的空间。现在我的情况是 /docker/overlay2 磁盘大小比 docker system df 的输出要大得多。这就是我一直深入研究这个问题的原因。再次感谢您的回复,先生。我想我需要阅读更多有关Docker文档,或者完全删除并重新启动它。我只需要保留一个Postgres数据库,并将其挂载。 - qichao_he
4
"docker system prune -a -f" 对我在“Docker版本17.09.0-ce”上有效,但只有在停止所有容器后才能生效,这真是令人沮丧。有人用更新的版本尝试过吗? - Bruno
24
我会说,“支持”的方式对我也不起作用。执行所有的 docker system prune -a、docker volume prune、docker image prune 和 docker container prune,仍然导致我的 Docker 占用了 80% 的磁盘空间。这是在所有容器停止的情况下。 - Craig Brett
7
我知道这是“官方”答案,但这个答案相当存在缺陷,会留下大量的数据,特别是对于不再使用的镜像和容器的overlay2差异文件夹。我的Docker应该只使用约100G,但实际使用超过了200G。 - Novaterata
显示剩余5条评论

131

我发现这对我来说效果最佳:

docker image prune --all

默认情况下,即使未使用,Docker也不会删除已命名的镜像。 该命令将删除未使用的镜像。

请注意,镜像中的每个层都是位于/usr/lib/docker/overlay2/文件夹内的文件夹。


4
“图像修剪”比“系统修剪”效果好得多。谢谢! - DavidG
10
警告!这将非常破坏性,因为它会删除所有未运行容器的图像。如果这些容器属于您并且尚未推送到注册表,则您将需要花费数小时来重新构建它们。但它仍然无法超越 docker system df 显示的限制(您可能仍然没有足够的空间,需要手动清理 overlay2 垃圾场)。 - mirekphd
4
好的,它确实会移除图片。 - Sarke
1
这个可以用,但是请注意,它会删除容器之外的所有内容。 - jimh
1
@jimh 不是这样的。你根本没有明确指出到底会被删除什么。显然,你并不是字面意思。但你实际上想表达的是什么 - 仍然是个谜。请具体说明。 - whyer
显示剩余7条评论

58

我遇到了这个问题...巨大的日志是罪魁祸首。日志在这里:

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

您可以在运行命令行或compose文件中进行管理。请参见:配置日志驱动程序

我个人将以下三行添加到我的docker-compose.yml文件中:

my_container:
  logging:
    options:
      max-size: 10m

2
你能在答案中添加一些链接中的代码吗? - RtmY
希望能够得到如何识别哪个容器拥有巨大日志文件的信息。我有很多容器和日志文件,有些非常庞大,而有些则很小。 - Micah Zoltu
这怎么回答了OP的问题?! - Slavik Meltser
3
这个回答是一个部分的答案,尤其是如果“日志”是个问题(也许我们可以通过一些编辑来改善它?)。在看到这个答案之前,我正准备从我的过度充满overlay2的大目录中随机删除。在我的情况下,/var/lib/docker的总容量为50GB,其中36GB被一个文件所占用:/var/lib/docker/overlay2/<container id>/diff/var/log/faillog。假设这个文件不是保持一切顺畅的核心,我的短期黑客方法就是将其删除(也许我还会调整我的docker-compose)。 - D. Woods

41

我也遇到了快速增长的overlay2的问题。

/var/lib/docker/overlay2是一个文件夹,其中存储了容器的可写层。使用命令docker system prune -a可能只有在容器停止并删除时才有效。

我能够通过进入overlay2并进行调查来找出占用空间的原因。

该文件夹包含其他名为哈希的文件夹。每个文件夹都有几个文件夹,包括diff文件夹。

diff文件夹- 包含由容器编写的实际差异,并具有与您的容器完全相同的文件夹结构(至少在我的情况下是ubuntu 18 ...)

所以我使用了du -hsc /var/lib/docker/overlay2/LONGHASHHHHHHH/diff/tmp来找出污染的文件夹,即我的容器内的/tmp

因此,我使用了-v /tmp/container-data/tmp:/tmp参数来运行docker run命令,将内部/tmp文件夹映射到主机上,并在主机上设置一个cron来清理这个文件夹。

cron任务很简单:

  • sudo nano /etc/crontab
  • */30 * * * * root rm -rf /tmp/container-data/tmp/*
  • 保存并退出

注意: overlay2 是系统Docker文件夹,他们随时可能更改其结构。上述所有内容都是基于我在那里看到的。只能进入Docker文件夹结构,因为系统已经完全没有空间,甚至不允许我通过ssh进入Docker容器。


感谢您的回答,我们将旧的数据/应用程序放入容器中,生成了大量的/var/log/apache2/error.log。我重置了error.log和access.log,并添加了一个新的卷,以便更轻松地进行管理。 - bcag2
4
只是一个小问题:您应该使用crontab -e命令编辑crontab,这个命令会在保存之前检查有效性。 - programagor
你的回答对我解决这个问题非常有帮助。谢谢。 - EM90

28

如果您的系统还用于构建映像,那么您可能需要查看使用以下命令清理构建器创建的垃圾:

docker buildx prune --all

docker builder prune --all

4
这个回答值得更多的关注。不用清理整个Docker系统,它帮我节省了64GB的空间,同时保留了所有镜像。非常感谢。 - Martin
非常有用,谢谢!这对我来说产生了最大的区别。 - hedleyroos
4
谢谢,这个命令清除了我构建服务器上360.7GB的Docker缓存。我只删除了镜像、容器和卷,忘记了构建缓存。 - Crayon
这应该是被接受的答案。产生了很大的影响。 - undefined
docker system prune -a 应该会清除构建缓存(根据其警告),但实际上并没有! - undefined

19

背景

这个问题的责任可以归结为我们容器卷的错误配置和docker泄漏(未能释放)写入这些卷的临时数据之间的问题。我们应该映射(要么到主机文件夹,要么到其他持久性存储索赔)我们所有容器的临时/日志/临时文件夹,其中我们的应用程序频繁和/或大量写入。Docker不负责清理默认位于/ var / lib / docker / overlay2 / * / diff / *中的所有自动创建的所谓EmptyDirs的内容。这些“非持久性”文件夹的内容应在容器停止后由docker自动清除,但显然并没有(如果容器仍在运行,则可能甚至无法从主机侧清除它们 - 它可以运行几个月)。

解决方法

解决方法需要仔细的手动清理,并且虽然已经在其他地方进行了描述,但您仍然可以从我的案例研究中找到一些提示,我尽可能地让它具有指导性和可推广性。

所以发生了什么事情是罪魁祸首应用程序(在我的案例中为clair-scanner)设法在几个月内将数百吉字节的数据写入了docker的overlay2/diff/tmp子文件夹中。

du -sch /var/lib/docker/overlay2/<long random folder name seen as bloated in df -haT>/diff/tmp

271G total

由于/diff/tmp下的所有子文件夹都很容易理解(所有这些文件夹都是以clair-scanner-*的形式存在,同时创建日期也过时了),因此我停止了相关的容器 (docker stop clair),并仔细地从diff/tmp中删除了这些过时的子文件夹,先从最旧的一个开始谨慎地进行测试,检查其对docker引擎的影响(这确实需要重新启动[systemctl restart docker]才能回收磁盘空间):

rm -rf $(ls -at /var/lib/docker/overlay2/<long random folder name seen as bloated in df -haT>/diff/tmp | grep clair-scanner | tail -1)

我成功地回收了数百GB的磁盘空间,而无需重新安装Docker或清除其整个文件夹。所有运行中的容器都必须在某一点上停止,因为需要重新启动Docker守护程序才能回收磁盘空间,因此请确保首先您的故障转移容器在/其他节点上正常运行。但是,我希望docker prune命令也可以通过另一个开关清除过时的/diff/tmp(甚至/diff/*)数据。这是一个三年前的问题,您可以在Docker论坛上阅读它丰富多彩的历史。2019年提出了一个旨在解决以上方案的应用程序日志变体,在几个设置中似乎已经起作用:https://forums.docker.com/t/some-way-to-clean-up-identify-contents-of-var-lib-docker-overlay/30604

5
谢谢您实际上关注真正的问题。 - Novaterata

14

朋友们,为了保持一切整洁干净,您可以使用以下命令:

docker system prune -a && docker volume prune

这对我来说是个好消息。我有一些未被引用的Docker卷。我执行了“docker system prune”命令,它删除了未使用的Docker卷。感谢@Tiago Barreto。 - waruna k
9
请注意,“docker volume prune”命令将删除所有从Docker持久化到主机磁盘的数据......而“system prune”则是安全的。 - Herz3h

12

警告:请勿在生产系统中使用

/# df
...
/dev/xvda1      51467016 39384516   9886300  80% /
...

好的,让我们先尝试系统清理

#/ docker system prune --volumes
...
/# df
...
/dev/xvda1      51467016 38613596  10657220  79% /
...

效果不是很好,似乎只清理了几兆的空间。现在让我们来疯狂一点:

/# sudo su
/# service docker stop
/# cd /var/lib/docker
/var/lib/docker# rm -rf *
/# service docker start
/var/lib/docker# df
...
/dev/xvda1      51467016 8086924  41183892  17% /
...

不错!但是请记住,除了一次性服务器之外,不建议在其他任何地方使用此功能。在这种情况下,Docker内部数据库将无法找到这些叠加层,可能会造成意想不到的后果。


2
完全清空/var/lib/docker目录(确保守护进程已停止,且该目录不包含特殊的文件系统挂载或类似内容)实际上是回到原点的一种有效而快速的方法。我不确定为什么你会被所有人点踩。Docker试图自我修复,并在必要时重新初始化/var/lib/docker目录。 - L0j1k
2
天啊,终于有一个可行的答案了。我已经修剪和做了4个小时的事情,但我应该只是停止docker服务,把所有东西放进垃圾桶,然后重新启动它。 - Osi
它“能用”,但它也会删除Docker生成的所有内容。因此,这并不是一个好的解决方案。 - Akito
我有一个构建节点,从Jenkins接收任务来构建镜像、上传它们,然后删除它们。随着构建的进行,它不断积累。每次构建之前,我都会执行docker system prune --all --force命令,但这并没有解决问题。overlay2目录占用了超过70GB的空间。我在构建过程中添加了这些步骤,现在它已经可以正常运行了。 - Khalid Ibrahim

7

“官方”答案,使用“prune”命令清理时,实际上并不会清理overlay2文件夹中的垃圾。

所以,回答原始问题,可以采取以下措施:

免责声明:在应用此方法时要小心。这可能导致破坏您的Docker对象!

  • 列出overlay2中的文件夹名称(哈希值)
  • 检查您需要的Docker对象(镜像、容器等),(停止的容器或当前未在任何容器内的映像并不意味着您不需要它们)。
  • 当您进行检查时,将看到它给您提供了与您的对象相关的哈希值,包括overlay2的文件夹。
  • overlay2的文件夹执行grep操作
  • 注意所有使用grep找到的文件夹
  • 现在,您可以删除overlay2的文件夹,这些文件夹没有被您需要的任何Docker对象所引用。

例如:

假设在您的overlay2目录中有以下文件夹,

a1b28095041cc0a5ded909a20fed6dbfbcc08e1968fa265bc6f3abcc835378b5
021500fad32558a613122070616963c6644c6a57b2e1ed61cb6c32787a86f048

您只拥有一个ID为c777cf06a6e3的图像。

接下来,执行以下操作:

docker inspect c777cf06a6e3 | grep a1b2809
docker inspect c777cf06a6e3 | grep 021500

假设第一个命令找到了某些内容,而第二个命令没有找到。然后,您可以删除 overlay2 的 0215... 文件夹:
rm -r 021500fad32558a613122070616963c6644c6a57b2e1ed61cb6c32787a86f048

回答问题的标题:

  • 是的,如果您发现它没有使用,直接删除overlay2文件夹是安全的。
  • 否则,如果您发现它正在使用或不确定,直接删除它是不安全的。

你没有明确验证该层是否未被使用,需要检查每个容器和镜像,因为层在镜像之间共享。如果容器已停止且镜像未使用,则 docker prune -a 将删除任何镜像和层未被任何镜像使用的内容。 - BMitch
1
是的,我已经检查了它们中的每一个。如果你有成千上万个命令可以一次性检查所有内容。正如我在回答中已经说明的那样,修剪对于垃圾不起作用!不知何故,在使用修剪删除了可能的所有小型Docker对象之后,overlay2仍然充满了几GB的垃圾!Docker对磁盘的管理远远不够智能。此外,修剪是非常危险的命令!我的容器可能已经停止,但这并不意味着我不需要它!它甚至没有警告,如果我确认该命令将删除哪些镜像、容器等。 - Mert Mertce
从/var/lib/docker/overlay2目录中,您可以使用这个微型脚本快速回答问题:for dir in `\ls`; do echo $dir; docker inspect ad8cf8bd0bdb | grep $dir | wc; done。您需要将ad8cf8bd0bdb替换为您自己的容器ID。任何返回计数为0的都是可以清理的候选项。 - Andrew Prock

5

在上面的评论中,人们建议修剪系统,例如清除悬空卷、镜像、退出容器等。有时候您的应用程序会成为罪魁祸首,它在很短的时间内生成了太多的日志,如果您使用一个空目录卷(本地卷),这会填满/var分区。在这种情况下,我发现以下命令非常有趣,可以找出占用我的/var分区磁盘空间的内容。

du -ahx /var/lib | sort -rh | head -n 30

这个命令将列出一个单磁盘上占用空间最多的前30个目录或文件。如果您正在使用容器的外部存储,则运行du命令需要消耗大量时间。此命令不会计算挂载的卷,并且速度更快。您将获得占用空间的确切目录/文件,然后可以转到这些目录并检查哪些文件有用或无用。如果这些文件是必需的,那么您可以通过修改应用程序以使用该位置的持久性存储或更改该文件的位置来将它们移动到一些持久性存储中。对于其余的文件,您可以清除它们。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接