简体   繁体   English

Docker 在 macOS 上填满存储空间

[英]Docker filling up storage on macOS

(Post created on Oct 05 '16) (帖子创建于 16 年 10 月 5 日)

I noticed that every time I run an image and delete it, my system doesn't return to the original amount of available space.我注意到每次运行图像并将其删除时,我的系统都不会恢复到原始可用空间量。

The lifecycle I'm applying to my containers is:我应用于我的容器的生命周期是:

> docker build ...
> docker run CONTAINER_TAG
> docker stop CONTAINER_TAG
> rm docker CONTAINER_ID
> rmi docker image_id

[ running on a default mac terminal ] [在默认 mac 终端上运行]

The containers in fact were created from custom images, running from node and a standard redis. My OS is OSX 10.11.6.实际上,容器是从自定义映像创建的,从节点和标准 redis 运行。我的操作系统是 OSX 10.11.6。

At the end of the day I see I keep losing Mbs.在一天结束时,我发现我一直在失去 Mbs。 How can I face this problem?我该如何面对这个问题?

EDITED POST编辑后的帖子

2020 and the problem persists, leaving this update for the community: 2020 年,问题仍然存在,将此更新留给社区:

Today running:今天跑步:

  • macOS 10.13.6 macOS 10.13.6
  • Docker Engine 18.9.2 Docker 引擎 18.9.2
  • Docker Desktop Cli 2.0.0.3 Docker 桌面客户端 2.0.0.3

The easiest way to workaround the problem is to prune the system with the Docker utilties.解决该问题的最简单方法是使用 Docker 实用程序修剪系统。

docker system prune -a --volumes

WARNING:警告:

By default, volumes are not removed to prevent important data from being deleted if there is currently no container using the volume.默认情况下,如果当前没有容器使用该卷,则不会删除卷以防止删除重要数据。 Use the --volumes flag when running the command to prune volumes as well:运行命令时也使用--volumes标志来修剪卷:

Docker now has a single command to do that: Docker 现在有一个命令可以做到这一点:

docker system prune -a --volumes

See the Docker system prune docs请参阅Docker system prune文档

There are three areas of Docker storage that can mount up, because Docker is cautious - it doesn't automatically remove any of them: exited containers, unused container volumes, unused image layers. Docker 存储的三个区域可以挂载,因为 Docker 很谨慎——它不会自动删除任何一个:退出的容器、未使用的容器卷、未使用的镜像层。 In a dev environment with lots of building and running, that can be a lot of disk space.在需要大量构建和运行的开发环境中,这可能需要大量磁盘空间。

These three commands clear down anything not being used:这三个命令清除未使用的任何内容:

  • docker rm $(docker ps -f status=exited -aq) - remove stopped containers docker rm $(docker ps -f status=exited -aq) - 删除停止的容器
  • docker rmi $(docker images -f "dangling=true" -q) - remove image layers that are not used in any images docker rmi $(docker images -f "dangling=true" -q) - 删除任何图像中未使用的图像层
  • docker volume rm $(docker volume ls -qf dangling=true) - remove volumes that are not used by any containers. docker volume rm $(docker volume ls -qf dangling=true) - 删除未被任何容器使用的卷。

These are safe to run, they won't delete image layers that are referenced by images, or data volumes that are used by containers.这些可以安全运行,它们不会删除图像引用的图像层或容器使用的数据卷。 You can alias them, and/or put them in a CRON job to regularly clean up the local disk.您可以为它们设置别名,和/或将它们放在 CRON 作业中以定期清理本地磁盘。

It is also worth mentioning that file size of docker.qcow2 (or Docker.raw on High Sierra with Apple Filesystem) can seem very large (~64GiB), larger than it actually is, when using the following command:还值得一提的是,当使用以下命令时,docker.qcow2(或 High Sierra 上的 Docker.raw 与 Apple 文件系统)的文件大小可能看起来非常大(~64GiB),比实际大:

  • ls -klsh Docker.raw

This can be somehow misleading because it will output the logical size of the file rather than its physical size.这在某种程度上可能会产生误导,因为它将输出文件的逻辑大小而不是其物理大小。

To see the physical size of the file you can use this command:要查看文件的物理大小,您可以使用以下命令:

  • du -h Docker.raw

Source: https://docs.docker.com/docker-for-mac/faqs/#disk-usage来源: https : //docs.docker.com/docker-for-mac/faqs/#disk-usage

Why does the file keep growing?为什么文件一直在增长?

If Docker is used regularly, the size of the Docker.raw (or Docker.qcow2 ) can keep growing, even when files are deleted.如果经常使用 Docker,即使文件被删除, Docker.raw (或Docker.qcow2 )的大小也会继续增长。

To demonstrate the effect, first check the current size of the file on the host:为了演示效果,首先检查主机上文件的当前大小:

$ cd ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/
$ ls -s Docker.raw
9964528 Docker.raw

Note the use of -s which displays the number of filesystem blocks actually used by the file.请注意-s的使用,它显示文件实际使用的文件系统块的数量。 The number of blocks used is not necessarily the same as the file “size”, as the file can be sparse .使用的块数不一定与文件“大小”相同,因为文件可以是稀疏的

Next start a container in a separate terminal and create a 1GiB file in it:接下来在单独的终端中启动一个容器并在其中创建一个 1GiB 文件:

$ docker run -it alpine sh
# and then inside the container:
/ # dd if=/dev/zero of=1GiB bs=1048576 count=1024
1024+0 records in
1024+0 records out
/ # sync

Back on the host check the file size again:回到主机上再次检查文件大小:

$ ls -s Docker.raw 
12061704 Docker.raw

Note the increase in size from 9964528 to 12061704 , where the increase of 2097176 512 -byte sectors is approximately 1GiB, as expected.请注意大小从9964528增加到12061704 ,其中2097176 512字节扇区的增加约为 1GiB,正如预期的那样。 If you switch back to the alpine container terminal and delete the file:如果切换回alpine容器终端并删除文件:

/ # rm -f 1GiB
/ # sync

then check the file on the host:然后检查主机上的文件:

$ ls -s Docker.raw 
12059672 Docker.raw

The file has not got any smaller!文件没有变小! Whatever has happened to the file inside the VM, the host doesn't seem to know about it.无论 VM 内的文件发生了什么,主机似乎都不知道。

Next if you re-create the “same” 1GiB file in the container again and then check the size again you will see:接下来,如果您再次在容器中重新创建“相同”的1GiB文件,然后再次检查大小,您将看到:

$ ls -s Docker.raw 
14109456 Docker.raw

It's got even bigger!它变得更大了! It seems that if you create and destroy files in a loop, the size of the Docker.raw (or Docker.qcow2 ) will increase up to the upper limit (currently set to 64 GiB), even if the filesystem inside the VM is relatively empty.看起来,如果你在一个循环中创建和销毁文件, Docker.raw (或Docker.qcow2 )的大小会增加到上限(目前设置为 64 GiB),即使 VM 内部的文件系统相对空的。

The explanation for this odd behaviour lies with how filesystems typically manage blocks.这种奇怪行为的解释在于文件系统通常如何管理块。 When a file is to be created or extended, the filesystem will find a free block and add it to the file.当要创建或扩展文件时,文件系统会找到一个空闲块并将其添加到文件中。 When a file is removed, the blocks become “free” from the filesystem's point of view, but no-one tells the disk device.当一个文件被删除时,从文件系统的角度来看,这些块变得“空闲”,但没有人告诉磁盘设备。 Making matters worse, the newly-freed blocks might not be re-used straight away – it's completely up to the filesystem's block allocation algorithm.更糟糕的是,新释放的块可能不会立即重新使用——这完全取决于文件系统的块分配算法。 For example, the algorithm might be designed to favour allocating blocks contiguously for a file: recently-freed blocks are unlikely to be in the ideal place for the file being extended.例如,该算法可能被设计为有利于为文件连续分配块:最近释放的块不太可能位于扩展文件的理想位置。

Since the block allocator in practice tends to favour unused blocks, the result is that the Docker.raw (or Docker.qcow2 ) will constantly accumulate new blocks, many of which contain stale data.由于块分配器在实践中倾向于支持未使用的块,结果是Docker.raw (或Docker.qcow2 )将不断积累新块,其中许多包含陈旧数据。 The file on the host gets larger and larger, even though the filesystem inside the VM still reports plenty of free space.主机上的文件变得越来越大,即使 VM 内的文件系统仍然报告有足够的可用空间。

TRIM修剪

A TRIM command (or a DISCARD or UNMAP ) allows a filesystem to signal to a disk that a range of sectors contain stale data and they can be forgotten. TRIM命令(或DISCARDUNMAP )允许文件系统向磁盘发出信号,表明一系列扇区包含陈旧数据并且可以忘记它们。 This allows:这允许:

  • an SSD drive to erase and reuse the space, rather than spend time shuffling it around;一个 SSD 驱动器来擦除和重用空间,而不是花时间四处移动; and
  • Docker for Mac to deallocate the blocks in the host filesystem, shrinking the file. Docker for Mac 释放主机文件系统中的块,缩小文件。

So how do we make this work?那么我们如何进行这项工作呢?

Automatic TRIM in Docker for Mac Docker for Mac 中的自动修剪

In Docker for Mac 17.11 there is a containerd “task” called trim-after-delete listening for Docker image deletion events.在 Docker for Mac 17.11 中,有一个容器化的“任务”,称为trim-after-delete用于监听 Docker 镜像删除事件。 It can be seen via the ctr command:可以通过ctr命令查看:

$ docker run --rm -it --privileged --pid=host walkerlee/nsenter -t 1 -m -u -i -n ctr t ls
TASK                    PID     STATUS    
vsudd                   1741    RUNNING
acpid                   871     RUNNING
diagnose                913     RUNNING
docker-ce               958     RUNNING
host-timesync-daemon    1046    RUNNING
ntpd                    1109    RUNNING
trim-after-delete       1339    RUNNING
vpnkit-forwarder        1550    RUNNING

When an image deletion event is received, the process waits for a few seconds (in case other images are being deleted, for example as part of a docker system prune ) and then runs fstrim on the filesystem.当收到图像删除事件时,该进程会等待几秒钟(以防其他图像被删除,例如作为fstrim 系统 prune 的一部分),然后在文件系统上运行fstrim

Returning to the example in the previous section, if you delete the 1 GiB file inside the alpine container回到上一节的例子,如果删除alpine容器内的 1 GiB 文件

/ # rm -f 1GiB

then run fstrim manually from a terminal in the host:然后从主机中的终端手动运行fstrim

$ docker run --rm -it --privileged --pid=host walkerlee/nsenter -t 1 -m -u -i -n fstrim /var/lib/docker

then check the file size:然后检查文件大小:

$ ls -s Docker.raw 
9965016 Docker.raw

The file is back to (approximately) it's original size – the space has finally been freed!文件恢复到(大约)原始大小——空间终于被释放了!

Hopefully this blog will be helpful, also checkout the following macos docker utility scripts for this problem:希望这篇博客会有所帮助,还可以查看以下针对此问题的 macos docker 实用程序脚本:

https://github.com/wanliqun/macos_docker_toolkit https://github.com/wanliqun/macos_docker_toolkit

Docker on Mac has an additional problem that is hurting a lot of people: the docker.qcow2 file can grow out of proportions (up to 64gb) and won't ever shrink back down on its own. Mac 上的 Docker 有一个额外的问题,它伤害了很多人:docker.qcow2 文件可以不成比例地增长(高达 64GB)并且永远不会自行缩小。

https://github.com/docker/for-mac/issues/371 https://github.com/docker/for-mac/issues/371

As stated in one of the replies by djs55 this is in the planning to be fixed, but its not a quick fix.正如 djs55 的其中一个回复所述,这是在计划修复中,但不是快速修复。 Quote:报价:

The .qcow2 is exposed to the VM as a block device with a maximum size of 64GiB. .qcow2 作为最大大小为 64GiB 的块设备公开给 VM。 As new files are created in the filesystem by containers, new sectors are written to the block device.随着容器在文件系统中创建新文件,新扇区被写入块设备。 These new sectors are appended to the .qcow2 file causing it to grow in size, until it eventually becomes fully allocated.这些新扇区被附加到 .qcow2 文件中,导致它的大小增加,直到它最终被完全分配。 It stops growing when it hits this maximum size.当它达到这个最大尺寸时它停止增长。

... ...

We're hoping to fix this in several stages: (note this is still at the planning / design stage, but I hope it gives you an idea)我们希望分几个阶段解决这个问题:(注意这仍处于规划/设计阶段,但我希望它能给你一个想法)

1) we'll switch to a connection protocol which supports TRIM, and implement free-block tracking in a metadata file next to the qcow2. 1)我们将切换到支持TRIM的连接协议,并在qcow2旁边的元数据文件中实现空闲块跟踪。 We'll create a compaction tool which can be run offline to shrink the disk (a bit like the qemu-img convert but without the dd if=/dev/zero and it should be fast because it will already know where the empty space is)我们将创建一个可以离线运行的压缩工具来缩小磁盘(有点像 qemu-img 转换,但没有 dd if=/dev/zero 并且它应该很快,因为它已经知道空白空间在哪里)

2) we'll automate running of the compaction tool over VM reboots, assuming it's quick enough 2) 我们将在虚拟机重启时自动运行压缩工具,假设它足够快

3) we'll switch to an online compactor (which is a bit like a GC in a programming language) 3)我们将切换到在线压缩器(有点像编程语言中的GC)

We're also looking at making the maximum size of the .qcow2 configurable.我们也在考虑使 .qcow2 的最大大小可配置。 Perhaps 64GiB is too large for some environments and a smaller cap would help?也许 64GiB 对于某些环境来说太大了,较小的上限会有所帮助吗?


Update 2019 : many updates have been done to Docker for Mac since this answer was posted to help mitigate problems (notably: supporting a different filesystem). 2019 年更新:自从发布此答案以帮助缓解问题(特别是:支持不同的文件系统)以来,Docker for Mac 已经进行了许多更新。

Cleanup is still not fully automatic though, you may need to prune from time to time.清理仍然不是全自动的,您可能需要不时修剪。 For a single command that can help to cleanup disk space, see zhongjiajie's answer .有关可以帮助清理磁盘空间的单个命令,请参阅zhongjiajie 的回答

docker container prune
docker system prune
docker image prune
docker volume prune

i'm not sure if it is related to the current topic, but this been a solution for me personally我不确定它是否与当前主题相关,但这对我个人来说是一个解决方案

open docker settings -> resources -> disk image size - 16gb打开 docker 设置 -> 资源 -> 磁盘映像大小 - 16gb

There are several options on how to limit docker diskspace, I'd start by limiting/rotating the logs: Docker container logs taking all my disk space关于如何限制 docker 磁盘空间有几个选项,我首先限制/旋转日志: Docker 容器日志占用了我所有的磁盘空间

Eg if you have a recent docker version, you can start it with an --log-opt max-size=50m option per container.例如,如果您有最新的 docker 版本,则可以使用每个容器的--log-opt max-size=50m选项启动它。 Also - if you've got old, unused containers, you can consider having a look at the docker logs which are located at /var/lib/docker/containers/*/*-json.log另外 - 如果你有旧的、未使用的容器,你可以考虑查看位于/var/lib/docker/containers/*/*-json.log的 docker 日志

$ sudo docker system prune

WARNING!警告! This will remove:这将删除:

  • all stopped containers所有停止的容器
  • all networks not used by at least one container至少一个容器未使用的所有网络
  • all dangling images所有悬垂的图像
  • all dangling build cacheAre you sure you want to continue?所有悬空构建缓存您确定要继续吗? [y/N] [年/年]

Since nothing here was working for me, here's what I did.由于这里没有什么对我有用,这就是我所做的。 Check file size:检查文件大小:

ls -lhks ~/Library/Containers/com.docker.docker//Data/vms/0/data/Docker.raw

Then in the docker desktop simply reduce the disk image size (I was using raw format).然后在 docker 桌面中简单地减小磁盘映像大小(我使用的是原始格式)。 It will say it will delete everything, but by the time you are reading this post, you probably already have.它会说它会删除所有内容,但是当您阅读这篇文章时,您可能已经拥有了。 So that creates a fresh new empty file.这样就创建了一个全新的空文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM