如何清理Docker的覆盖目录?

107
我正在使用CoreOS和AWS的ECS来运行Docker。我有一个失败的镜像已经重新启动了多次,容器仍然存在-它们占满了我的驱动器分区。具体而言,/var/lib/docker/overlay/包含大量的文件/目录。
我知道docker-cleanup-volumes可以清理/volumes目录,但无法清理/overlay目录。 docker ps -a显示我的坏Docker容器尝试过250多次启动,但它们并没有在运行。
除了rm -rf /var/lib/docker/overlay/*,我应该如何清理这些内容?
12个回答

183

从我们这边来看,我们使用了:

sudo docker system prune -a -f

这帮我节省了3GB的空间!

我们还使用了一些著名的命令:

sudo docker rm -v $(sudo docker ps -a -q -f status=exited)
sudo docker rmi -f  $(sudo docker images -f "dangling=true" -q)
docker volume ls -qf dangling=true | xargs -r docker volume rm

我们把它放在cron上,以更有效地管理我们的磁盘空间。
参考: https://forums.docker.com/t/some-way-to-clean-up-identify-contents-of-var-lib-docker-overlay/30604/4

5
救星!我不知道为什么“df”会说我的EC2卷已满,直到我在“/var”目录上运行了“ncdu”,它带我来这里!我通过第一个命令回收了超过280 GB的空间! - Josh Yolles
3
小心第三个命令(... xargs -r docker volume rm)。确保在运行此命令时,可能使用这些卷的容器正在运行。否则,它们将被视为悬空状态,因此会被删除。 - Julien
1
有很多关于这个问题的讨论:https://github.com/moby/moby/issues/33775 很多人遇到了覆盖目录占用更多空间的问题,而且不清楚如何清理它。 - Mnebuerquo
已释放33GB空间...谢谢。 - Nick Grealy

15

这是我目前正在使用的笨拙方法。我不会接受它作为答案,因为我希望有更好的方法。

# delete old docker processes
docker rm `docker ps -a | grep Exited | awk '{print $1 }'`
  ignore_errors: true

# delete old images. will complain about still-in-use images.
docker rmi `docker images -aq`

2
awk 可以过滤:docker ps -a | awk '/Exited/{ print $1 }'。不错的技巧。 - Krzysztof Jabłoński

13

我已经将这个添加到了我的开发环境的bashrc中,并且习惯每天运行它。

function cleanup_docker() {
  docker ps -f status=exited -q | xargs -r docker rm
  docker images -f dangling=true -q | xargs -r docker rmi
}
在某些情况下,以下脚本可以释放更多的空间,因为它会尝试移除所有图像,并且会默默地失败:
function cleanup_docker_aggressive() {
  for i in $(docker images --no-trunc -q | sort -u)
  do
    docker rmi $i 2> /dev/null
  done
}

遗憾的是,它们与您的解决方案没有显著区别。

编辑:从Docker 1.13开始,您可以使用docker system

docker system df    # to check what is using space
docker system prune # cleans up also networks, build cache, etc

编辑:从Docker 2017.09开始,您还可以使用容器镜像

docker container prune
docker image prune -a

后者可以与诸如 --filter "until=24h" 这样的高级筛选器一起使用。


1
我已经清理了所有内容,但叠加目录仍然超过20GB,而活动容器和镜像仅共同使用6GB。 - vladkras
1
@vladkras - 如果可以的话,尝试逐个重启Docker容器(不仅是 halt+resume),然后再运行清理操作。很可能有一些东西产生了大量日志。如果这样做没有帮助,也许你没有正确计算预期使用情况?此外,我强烈建议切换到overlay2,除非某个服务正在产生大量日志输出,否则您应该可以节省60%以上的空间。 - analytik
请帮我保存我的sda一半的数据, docker version ─╯ 客户端: 版本:18.09.6 API版本:1.39 Go版本:go1.10.8 - Tiana987642

10
我们刚刚开始出现这个问题,btafarelo的答案让我有了部分解决方案,或者至少让我感到放心,可以删除sha256条目。
系统信息:在ELB后面运行CoreOS 1.12的EC2实例。
  • Drain the docker instance from the ELB
  • Shutdown docker

    systemctl stop docker
    rm -rf /var/lib/docker/overlay/*
    
  • Execute the results of the commands

    for d in $(find /var/lib/docker/image/overlay -type d -name '*sha256*'); do echo rm -rf $d/* ; done
    
  • reboot (easiest way to bring everything back up)

在服务重新启动后,这样做可以恢复大约25%的磁盘空间,且没有任何负面影响。


尝试了您的清理操作,结果所有服务创建都被拒绝,并显示错误消息“lstat /var/lib/docker/overlay”。 - tkyass
1
你是不是意外删除了覆盖目录?lstat 是用于符号链接的,但我的不是符号链接。 - Kevin McFadden
即使停止了Docker,我仍然有一些被锁定的文件夹在/var/lib/docker/overlay/中。我不得不手动卸载它们以便删除它们。 - Joel B

9

这不是真实情况!

/var/lib/docker/overlay2,顾名思义,包含了一堆overlay文件系统(可以参考这里进行简要介绍)。运行命令mount | grep overlay2,你会发现所有的/var/lib/docker/overlay2/*/merged文件夹都是overlay类型的挂载点。这意味着du所显示的并不是真实情况。为了了解这些文件夹(在磁盘上)实际占用了多少空间,你需要将注意力限制在overlayfs挂载的upper目录上(在docker中称为diff),例如:

du -sch /var/lib/docker/overlay2/*/diff
...
3.8G    total

作为对比,就我的情况而言:

> du -sch /var/lib/docker/overlay2
...
17G total

所以如果说磁盘上的所有空间都被使用了,并且被覆盖使用,那么说它不是真实的有什么帮助呢?我的磁盘写入现在失败了...所以它足够真实以至于干扰了操作。有没有一种命令可以将真实的磁盘使用与报告的磁盘使用对齐? - undefined
du并没有告诉你磁盘是否已满。也许你是指df?如果是这样,df所说的都是真实的。我相信我的回答已经解决了你的问题,告诉你如何只看到真实的部分。 - undefined
抱歉,我是说“df”,不好意思。 - undefined

7

docker ps

  • --quiet

  • --all

  • --filter status=exited


docker rm

  • --force

docker镜像

  • --quiet(仅返回ID)
  • --all(显示所有镜像,包括中间层镜像)
  • --filter dangling=true(过滤出悬空镜像)

docker rmi

  • -- 强制

你的hacky方式很好。

docker rm `docker ps -a | grep Exited | awk '{print $1 }'`

我的笨办法是

docker rm $(docker ps --all | awk '/ago/{print $1}')

一种稍微更清晰的方式是使用--quiet(-q)标志运行docker ps以仅获取ID号,再使用--filter status=exited来过滤出已退出的容器。
docker rm $(docker ps --filter status=exited --quiet) # remove stopped docker processes

或者使用带有--force (-f)标志的docker rm和带有--all (-a)标志的docker ps来关闭正在运行的容器。

docker rm --force $(docker ps --all --quiet) # remove all docker processes

可能是由于多次构建失败导致磁盘空间不足,主要原因是镜像文件。为了节省docker主机的磁盘空间,定期删除未使用的docker镜像。
docker rmi $(docker images --filter dangling=true --quiet) # clean dangling docker images

或者更加强制性地,您可以使用--force(-f)来清理--all(-a)的图像。
docker rmi --force $(docker images --all --quiet) # clean all possible docker images

@analytik的方法将其放入.bashrc函数中似乎是一个实用的想法。
function cleanup_docker() {
  docker rm --force $(docker ps --all --quiet) # remove all docker processes
  docker rmi $(docker images --filter dangling=true --quiet) # clean dangling docker images
}

如果您习惯于生成许多不需要的Docker镜像,请将其添加到.bash_logout中。



4
docker builder prune

这有助于清理Docker的overlay2文件夹


刚刚用这个清理了50GB的空间。显然,构建层也被缓存在这里,所以它不仅仅被运行的容器使用。 - undefined

2
我按照以下简单步骤进行操作:
步骤1:df -h [检查内存使用情况,确保内存被overlay文件夹使用]。
步骤2:sudo docker system prune [此命令将删除所有未使用的容器/镜像/网络]。
步骤3:sudo docker image prune -a [对于任何悬空镜像,如果存在的话]。
步骤4:df -h [确保已删除overlay数据]。

1
请注意,docker prune命令不会清理/var/lib/docker/overlay2目录。同时,建议不要仅删除覆盖层目录,因为这可能会影响现有的容器。我已经搜索了很多文章,但是除了清理整个docker状态之外,没有找到任何清理覆盖层目录的解决方案。
# Please understand that this will restart the docker engine in a completely empty state 
# i.e. you will lose all images, containers, volumes, networks, swarm state, etc. 
# You can obviously first take the backup of the directories that you want to keep and copy the contents back after restarting docker service.

service stop docker
rm -rf /var/lib/docker
service start docker

最后一个命令会将Docker服务重新启动,并恢复/var/lib/docker目录中的所有文件夹。


1

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