清洗docker/overlay2/安全吗

我在AWS EC2上运行了一些docker容器,/var/lib/docker/overlay2文件夹的磁盘大小增长得非常快。

我想知道删除它的内容是否安全? 或者如果docker有某种命令来释放一些磁盘使用


更新:

我实际上已经尝试了docker system prune -a,它回收了0Kb。

此外,我的/docker/overlay2磁盘大小比docker system df的输出大得多

在阅读docker文档和BMitch的回答后,我相信触摸这个文件夹是一个愚蠢的想法,我会尝试其他方法来回收我的磁盘空间。

292631 次浏览

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

引擎将在完全空的状态下重新启动,这意味着你将失去所有:

  • 图片
  • 容器
  • 名叫卷
  • 用户创建的网络
  • 群状态

我使用了“docker system prune -a”,它清洗了卷和overlay2下的所有文件

    [root@jasontest volumes]# docker system prune -a
WARNING! This will remove:
- all stopped containers
- all networks not used by at least one container
- all images without at least one container associated to them
- all build cache
Are you sure you want to continue? [y/N] y
Deleted Images:
untagged: ubuntu:12.04
untagged: ubuntu@sha256:18305429afa14ea462f810146ba44d4363ae76e4c8dfc38288cf73aa07485005
deleted: sha256:5b117edd0b767986092e9f721ba2364951b0a271f53f1f41aff9dd1861c2d4fe
deleted: sha256:8c7f3d7534c80107e3a4155989c3be30b431624c61973d142822b12b0001ece8
deleted: sha256:969d5a4e73ab4e4b89222136eeef2b09e711653b38266ef99d4e7a1f6ea984f4
deleted: sha256:871522beabc173098da87018264cf3e63481628c5080bd728b90f268793d9840
deleted: sha256:f13e8e542cae571644e2f4af25668fadfe094c0854176a725ebf4fdec7dae981
deleted: sha256:58bcc73dcf4050a4955916a0dcb7e5f9c331bf547d31e22052f1b5fa16cf63f8
untagged: osixia/openldap:1.2.1
untagged: osixia/openldap@sha256:6ceb347feb37d421fcabd80f73e3dc6578022d59220cab717172ea69c38582ec
deleted: sha256:a562f6fd60c7ef2adbea30d6271af8058c859804b2f36c270055344739c06d64
deleted: sha256:90efa8a88d923fb1723bea8f1082d4741b588f7fbcf3359f38e8583efa53827d
deleted: sha256:8d77930b93c88d2cdfdab0880f3f0b6b8be191c23b04c61fa1a6960cbeef3fe6
deleted: sha256:dd9f76264bf3efd36f11c6231a0e1801c80d6b4ca698cd6fa2ff66dbd44c3683
deleted: sha256:00efc4fb5e8a8e3ce0cb0047e4c697646c88b68388221a6bd7aa697529267554
deleted: sha256:e64e6259fd63679a3b9ac25728f250c3afe49dbe457a1a80550b7f1ccf68458a
deleted: sha256:da7d34d626d2758a01afe816a9434e85dffbafbd96eb04b62ec69029dae9665d
deleted: sha256:b132dace06fa7e22346de5ca1ae0c2bf9acfb49fe9dbec4290a127b80380fe5a
deleted: sha256:d626a8ad97a1f9c1f2c4db3814751ada64f60aed927764a3f994fcd88363b659
untagged: centos:centos7
untagged: centos@sha256:2671f7a3eea36ce43609e9fe7435ade83094291055f1c96d9d1d1d7c0b986a5d
deleted: sha256:ff426288ea903fcf8d91aca97460c613348f7a27195606b45f19ae91776ca23d
deleted: sha256:e15afa4858b655f8a5da4c4a41e05b908229f6fab8543434db79207478511ff7


Total reclaimed space: 533.3MB
[root@jasontest volumes]# ls -alth
total 32K
-rw-------  1 root root  32K May 23 21:14 metadata.db
drwx------  2 root root 4.0K May 23 21:14 .
drwx--x--x 14 root root 4.0K May 21 20:26 ..

警告:不要在生产系统中使用

/# 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% /
...
< p >好了! 只需要记住,除了一次性服务器,不建议使用这种方法。此时,Docker的内部数据库将无法找到任何这些覆盖,这可能会导致意想不到的后果

我有这样的问题…那是一根巨大的木头。日志如下:

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

您可以在运行命令行或撰写文件中进行管理。看这里:配置日志驱动程序

我个人将这3行添加到我的docker-compose中。Yml文件:

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

也有快速增长的overlay2的问题

/var/lib/docker/overlay2 -是docker存储容器可写层的文件夹。 docker system prune -a -只有当容器停止并被删除时才可以工作

在我的i中,我能够通过进入overlay2并进行调查来计算出什么消耗空间。

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

diff文件夹-包含一个容器写的实际差异,与你的容器的文件夹结构相同(至少在我的情况下- ubuntu 18…)

因此,我使用__ABC0来计算出容器内的/tmp是被污染的文件夹

所以作为一个解决方案,我已经使用-v /tmp/container-data/tmp:/tmp参数为docker run命令来映射内部的/tmp文件夹到主机,并在主机上设置一个cron来清除该文件夹。

Cron任务很简单:

  • sudo nano /etc/crontab
  • */30 * * * * root rm -rf /tmp/container-data/tmp/*
  • save and exit

注意:overlay2是系统docker文件夹,他们可以随时改变它的结构。以上一切都是基于我在里面看到的。不得不进入docker文件夹结构,因为系统完全没有空间,甚至不允许我ssh进入docker容器。

我发现这个方法最适合我:

docker image prune --all

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

注意图像中的每一层都是/usr/lib/docker/overlay2/文件夹中的一个文件夹。

背景

该问题的责任可以分为容器卷的错误配置和docker泄漏(未能释放)写入这些卷的临时数据的问题。我们应该映射(到主机文件夹或其他持久存储声明)所有容器外的临时/日志/草稿文件夹,我们的应用程序经常和/或大量写入。Docker不负责清除所有自动创建的所谓的EmptyDirs,默认位于/var/lib/docker/overlay2/*/diff/*中。这些“非持久性”文件夹的内容应该在容器停止后由docker自动清除,但显然没有(如果容器仍在运行,它们甚至不可能从主机端清除——它一次可以运行几个月)。

解决方案

解决方案需要仔细的手动清理,虽然已经在其他地方描述过,但您仍然可以从我的案例研究中找到一些提示,我试图使其尽可能具有启发性和普遍性。

所以发生的事情是罪魁祸首应用程序(在我的情况下clair-scanner)设法写了几个月数百gb的数据到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/*)数据(通过另一个开关)。

这是一个有3年历史的问题了,你可以在Docker论坛上阅读它丰富多彩的历史,其中针对上述解决方案的应用程序日志的变体在2019年被提出,并且似乎在几个设置中起了作用:https://forums.docker.com/t/some-way-to-clean-up-identify-contents-of-var-lib-docker-overlay/30604

不要在生产环境中这样做

@ravi-luthra给出的答案在技术上是有效的,但它有一些问题!

在我的例子中,我只是试图恢复磁盘空间。lib/docker/overlay文件夹占用了30GB的空间,我只定期运行几个容器。看起来docker有一些数据泄漏的问题,一些临时数据在容器停止时没有被清除。

所以我删除了lib/docker/overlay文件夹的所有内容。在那之后,我的docker实例变得不可用。当我试图运行或构建任何容器时,它给了我这个错误:

failed to create rwlayer: symlink ../04578d9f8e428b693174c6eb9a80111c907724cc22129761ce14a4c8cb4f1d7c/diff /var/lib/docker/overlay2/l/C3F33OLORAASNIYB3ZDATH2HJ7: no such file or directory

经过反复试验,我通过跑步解决了这个问题

(警告:这将删除docker卷内的所有数据)

docker system prune --volumes -a

所以不建议做这样的脏清理,除非你完全了解系统是如何工作的。

/var/lib/docker中的所有内容都是容器的文件系统。如果你停止所有的容器并修剪它们,你应该以文件夹为空结束。你可能并不想那样做,所以不要随意删除里面的内容。有时候你可能会侥幸逃脱,但出于很多原因,这是不可取的。

你可以这样做:

sudo bash
cd /var/lib/docker
find . -type f | xargs du -b  | sort -n

您将看到的是底部显示的最大文件。如果你愿意,找出这些文件在什么容器中,用docker exec -ti containername -- /bin/sh输入这些容器并删除一些文件。

你也可以把docker system prune -a -f放在每日/每周的cron作业中,只要你不留下你所关心的停止的容器和卷。最好是找出它增长的原因,并在容器级别上纠正它们。

我最近遇到了一个类似的问题,overlay2变得越来越大,但我不知道是什么消耗了大量的空间。

df告诉我overlay2的大小约为24GB。

使用du,我试图找出占用空间的是什么,但失败了。

区别来自于删除的文件(在我的情况下主要是日志文件)仍然被一个进程(Docker)使用。因此,文件不会显示为du,但它所占用的空间将显示为df

重启主机有帮助。重新启动docker容器可能已经有所帮助了…… linuxquestions.org上的这篇文章帮助我解决了这个问题

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

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

该命令将列出占用单个磁盘空间最多的前30个。这意味着如果您的容器使用外部存储,那么运行du命令将花费大量时间。该命令不会对挂载卷进行计数。而且要快得多。您将获得消耗空间的确切目录/文件。然后你可以进入这些目录,检查哪些文件有用或没用。如果这些文件是必需的,那么你可以通过在应用程序中进行更改来使用该位置的持久存储或更改该文件的位置来将它们移动到某个持久存储中。休息时,你可以清理它们。

朋友们,为了保持一切清洁,你可以使用命令:

docker system prune -a && docker volume prune

Docker显然为运行的容器保留了映像的旧版本的映像层。如果你更新运行中的容器的镜像(相同的标签)而没有停止它,可能会发生这种情况,例如:

docker-compose pull
docker-compose up -d

在更新之前运行docker-compose down解决了它,停机时间在我的情况下不是一个问题。

我也有同样的问题,在我的实例中,这是因为' var/lib/docker '目录被挂载到一个运行的容器(在我的情况下谷歌/cadvisor),因此它阻止了docker修剪清理文件夹。停止容器,运行docker prune -然后重新运行容器解决了问题。

docker system prune -af && docker image prune -af

“Official"答:用“;prune"命令,实际上不清理overlay2文件夹中的垃圾。

所以,要回答最初的问题,我们可以做的是:

免责声明:应用此功能时请小心。这可能会导致Docker对象中断!

  • 列出overlay2中的文件夹名称(哈希值)
  • 检查你需要的Docker对象(图像,容器,…)(一个停止的容器或当前不在任何容器中的图像并不意味着你不需要它们)。
  • 当你检查时,你会看到它给你与你的对象相关的哈希值,包括overlay2的文件夹。
  • grep是否针对overlay2的文件夹
  • 注意在grep中找到的所有文件夹
  • 现在你可以删除没有被任何Docker对象引用的overlay2文件夹。

例子:

假设在你的overlay2目录中有这些文件夹,

a1b28095041cc0a5ded909a20fed6dbfbcc08e1968fa265bc6f3abcc835378b5
021500fad32558a613122070616963c6644c6a57b2e1ed61cb6c32787a86f048

你只有一个ID为c777cf06a6e3的图像。

然后,这样做:

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

想象一下,第一个命令找到了一些东西,而第二个命令什么也没有。

然后,您可以删除0215…overlay2的文件夹:

rm -r 021500fad32558a613122070616963c6644c6a57b2e1ed61cb6c32787a86f048

回答问题的题目:

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

如果你的系统也用于构建映像,你可以看看如何清理由构建器创建的垃圾,使用:

docker buildx prune --all

而且

docker builder prune --all
也许这个文件夹不是你的问题,不要用docker使用df -h的结果。 使用以下命令查看每个文件夹的大小:

echo; pwd; echo; ls -AlhF; echo; du -h --max-depth=1; echo; du-sh

基于莫特Mertce回答,我编写了以下脚本,包括旋转器和进度条。

然而,自从写了脚本之后,我注意到我们构建服务器上的额外目录是暂时的——也就是说,Docker似乎正在清理,尽管速度很慢。我不知道如果存在删除目录的竞争,Docker是否会感到不安。我们目前的解决方案是使用docuum和额外开销的很多 (150+GB)。

#!/bin/bash
[[ $(id -u) -eq 0 ]] || exec sudo /bin/bash -c "$(printf '%q ' "$BASH_SOURCE" "$@")"
progname=$(basename $0)
quiet=false
no_dry_run=false
while getopts ":qn" opt
do
case "$opt" in
q)
quiet=true
;;
n)
no_dry_run=true
;;
?)
echo "unexpected option ${opt}"
echo "usage: ${progname} [-q|--quiet]"
echo "    -q: no output"
echo "    -n: no dry run (will remove unused directories)"
exit 1
;;
esac
done
shift "$(($OPTIND -1))"


[[ ${quiet} = false ]] || exec /bin/bash -c "$(printf '%q ' "$BASH_SOURCE" "$@")" > /dev/null


echo "Running as: $(id -un)"


progress_bar() {
local w=80 p=$1;  shift
# create a string of spaces, then change them to dots
printf -v dots "%*s" "$(( $p*$w/100 ))" ""; dots=${dots// /.};
# print those dots on a fixed-width space plus the percentage etc.
printf "\r\e[K|%-*s| %3d %% %s" "$w" "$dots" "$p" "$*";
}


cd /var/lib/docker/overlay2
echo cleaning in ${PWD}
i=1
spi=1
sp="/-\|"
directories=( $(find . -mindepth 1 -maxdepth 1 -type d | cut -d/ -f2) )
images=( $(docker image ls --all --format "\{\{.ID}}") )
total=$((${#directories[@]} * ${#images[@]}))
used=()
for d in "${directories[@]}"
do
for id in ${images[@]}
do
((++i))
progress_bar "$(( ${i} * 100 / ${total}))" "scanning for used directories ${sp:spi++%${#sp}:1} "
docker inspect $id | grep -q $d
if [ $? ]
then
used+=("$d")
i=$(( $i + $(( ${#images[@]} - $(( $i % ${#images[@]} )) )) ))
break
fi
done
done
echo -e "\b\b " # get rid of spinner
i=1
used=($(printf '%s\n' "${used[@]}" | sort -u))
unused=( $(find . -mindepth 1 -maxdepth 1 -type d | cut -d/ -f2) )
for d in "${used[@]}"
do
((++i))
progress_bar "$(( ${i} * 100 / ${#used[@]}))" "scanning for unused directories ${sp:spi++%${#sp}:1} "
for uni in "${!unused[@]}"
do
if [[ ${unused[uni]} = $d ]]
then
unset 'unused[uni]'
break;
fi
done
done
echo -e "\b\b " # get rid of spinner
if [ ${#unused[@]} -gt 0 ]
then
[[ ${no_dry_run} = true ]] || echo "Could remove:  (to automatically remove, use the -n, "'"'"no-dry-run"'"'" flag)"
for d in "${unused[@]}"
do
if [[ ${no_dry_run} = true ]]
then
echo "Removing $(realpath ${d})"
rm -rf ${d}
else
echo " $(realpath ${d})"
fi
done
echo Done
else
echo "All directories are used, nothing to clean up."
fi

我导航到包含overlay2的文件夹。使用du -shc overlay2/*,我发现在overlay2中有25G的垃圾。运行docker system prune -af会显示Total Reclaimed Space: 1.687MB,所以我认为它无法清理它。然而,我随后再次运行du -shc overlay2/*,只看到overlay2中只有80K,所以它确实工作。

小心,docker撒谎:)。