Docker 填满 macOS 上的存储空间
Posted
技术标签:
【中文标题】Docker 填满 macOS 上的存储空间【英文标题】:Docker filling up storage on macOS 【发布时间】:2017-02-14 04:36:37 【问题描述】:(帖子创建于 2016 年 10 月 5 日)
我注意到每次运行图像并删除它时,我的系统都不会恢复到原来的可用空间量。
我应用于容器的生命周期是:
> docker build ...
> docker run CONTAINER_TAG
> docker stop CONTAINER_TAG
> rm docker CONTAINER_ID
> rmi docker image_id
[在默认的 mac 终端上运行]
容器实际上是从自定义图像创建的,从节点和标准 redis 运行。我的操作系统是 OSX 10.11.6。
在一天结束时,我发现我一直在失去 Mbs。我该如何面对这个问题?
编辑后的帖子
2020 年,问题仍然存在,将此更新留给社区:
今天跑步:
macOS 10.13.6 Docker 引擎 18.9.2 Docker 桌面 Cli 2.0.0.3解决此问题的最简单方法是使用 Docker 实用程序修剪系统。
docker system prune -a --volumes
【问题讨论】:
【参考方案1】:警告:
默认情况下,如果当前没有容器使用该卷,则不会删除卷以防止删除重要数据。在运行命令修剪卷时也使用
--volumes
标志:
Docker 现在有一个命令可以做到这一点:
docker system prune -a --volumes
见Docker system prune
docs
【讨论】:
今天的官方最佳解决方案。不理想但工作!感谢您为社区更新此内容@zhongjiajie 看起来duc
报告的是表观尺寸而不是实际尺寸,所以我需要避免对此感到如此震惊。对于使用它的其他人,在显示 gui 时按 a
在外观和实际大小之间切换。【参考方案2】:
Docker 存储的三个区域可以挂载,因为 Docker 很谨慎 - 它不会自动删除其中任何一个:退出的容器、未使用的容器卷、未使用的映像层。在具有大量构建和运行的开发环境中,这可能是大量磁盘空间。
这三个命令清除所有未使用的内容:
docker rm $(docker ps -f status=exited -aq)
- 移除停止的容器
docker rmi $(docker images -f "dangling=true" -q)
- 删除未在任何图像中使用的图像层
docker volume rm $(docker volume ls -qf dangling=true)
- 删除未被任何容器使用的卷。
这些可以安全运行,它们不会删除图像引用的图像层或容器使用的数据卷。您可以为它们设置别名,和/或将它们放入 CRON 作业中以定期清理本地磁盘。
【讨论】:
我尝试运行这 3 个命令,但它们都不起作用,而是 Docker 显示此示例消息"docker volume rm" requires at least 1 argument. See 'docker volume rm --help'. Usage: docker volume rm [OPTIONS] VOLUME [VOLUME...] Remove one or more volumes
@rashidkhan 我认为这是因为查询(在$
之后)没有返回任何结果。你试过accepted answer吗?【参考方案3】:
还值得一提的是,使用以下命令时,docker.qcow2(或 High Sierra 上的 Docker.raw 和 Apple Filesystem)的文件大小可能看起来非常大(~64GiB),比实际更大:
ls -klsh Docker.raw
这可能会产生某种误导,因为它会输出文件的逻辑大小而不是其物理大小。
要查看文件的物理大小,您可以使用以下命令:
du -h Docker.raw
来源:https://docs.docker.com/docker-for-mac/faqs/#disk-usage
【讨论】:
【参考方案4】:为什么文件一直在增长?
如果经常使用 Docker,Docker.raw
(或Docker.qcow2
)的大小可以保持增长,即使文件被删除。
为了演示效果,首先查看主机上文件的当前大小:
$ cd ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/
$ ls -s Docker.raw
9964528 Docker.raw
注意-s
的使用,它显示了文件实际使用的文件系统块的数量。使用的块数不一定与文件“大小”相同,因为文件可以是sparse。
接下来在单独的终端中启动一个容器,并在其中创建一个 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
回到主机再次检查文件大小:
$ ls -s Docker.raw
12061704 Docker.raw
注意大小从9964528
增加到12061704
,其中2097176
512
-byte 扇区的增加约为 1GiB,正如预期的那样。如果切换回alpine
容器终端并删除文件:
/ # rm -f 1GiB
/ # sync
然后检查主机上的文件:
$ ls -s Docker.raw
12059672 Docker.raw
文件没有变小!无论 VM 内的文件发生了什么变化,主机似乎都不知道。
接下来,如果你再次在容器中重新创建“相同”1GiB
文件,然后再次检查大小,你将看到:
$ ls -s Docker.raw
14109456 Docker.raw
它变得更大了!看来如果循环创建和销毁文件,Docker.raw
(或Docker.qcow2
)的大小会增加到上限(目前设置为64 GiB),即使VM内部的文件系统相对空。
这种奇怪行为的解释在于文件系统通常如何管理块。当要创建或扩展文件时,文件系统会找到一个空闲块并将其添加到文件中。当一个文件被删除时,从文件系统的角度来看,这些块变得“空闲”,但没有人告诉磁盘设备。更糟糕的是,新释放的块可能不会立即被重新使用——这完全取决于文件系统的块分配算法。例如,该算法可能被设计为支持为文件连续分配块:最近释放的块不太可能位于被扩展文件的理想位置。
由于实际中的块分配器倾向于偏爱未使用的块,结果是Docker.raw
(或Docker.qcow2
)将不断积累新块,其中许多包含陈旧数据。主机上的文件越来越大,尽管 VM 内的文件系统仍然报告有足够的可用空间。
修剪
TRIM 命令(或DISCARD
或UNMAP
)允许文件系统向磁盘发出信号,告知磁盘范围内的扇区包含陈旧数据并且可以将其遗忘。这允许:
那么我们如何做到这一点呢?
Docker for Mac 中的自动 TRIM
在 Docker for Mac 17.11 中有一个名为 trim-after-delete
的“任务”containerd 正在侦听 Docker 映像删除事件。可以通过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
***kit-forwarder 1550 RUNNING
当接收到图像删除事件时,进程会等待几秒钟(以防其他图像被删除,例如作为docker system prune 的一部分),然后在文件系统上运行fstrim
。
回到上一节的例子,如果你删除alpine
容器内的1 GiB文件
/ # rm -f 1GiB
然后从主机中的终端手动运行fstrim
:
$ docker run --rm -it --privileged --pid=host walkerlee/nsenter -t 1 -m -u -i -n fstrim /var/lib/docker
然后检查文件大小:
$ ls -s Docker.raw
9965016 Docker.raw
文件恢复到(大约)原来的大小——空间终于被释放了!
希望this blog 会有所帮助,还请查看以下针对此问题的 macOS docker 实用程序脚本:
https://github.com/wanliqun/macos_docker_toolkit
【讨论】:
【参考方案5】:Mac 上的 Docker 还存在一个让很多人感到痛苦的问题:docker.qcow2 文件可能会不成比例地增长(高达 64gb)并且不会自行缩小。
https://github.com/docker/for-mac/issues/371
正如 djs55 的其中一个回复所述,这是在计划中修复,但不是快速修复。引用:
.qcow2 作为块设备暴露给 VM,具有最大大小 64GiB。当容器在文件系统中创建新文件时, 新扇区被写入块设备。这些新领域是 附加到 .qcow2 文件导致它的大小增长,直到它 最终变为完全分配。当它碰到这个时它停止生长 最大尺寸。
...
我们希望分几个阶段解决此问题:(请注意,这仍处于 规划/设计阶段,但我希望它能给你一个想法)
1) 我们将切换到支持 TRIM 的连接协议,并且 在 qcow2 旁边的元数据文件中实现空闲块跟踪。 我们将创建一个可以离线运行的压缩工具来缩小 磁盘(有点像 qemu-img 转换但没有 dd if=/dev/zero 它应该很快,因为它已经知道空的位置 空间是)
2) 我们将在 VM 重新启动时自动运行压缩工具, 假设它足够快
3) 我们将切换到在线压缩器(有点像 GC 中的 编程语言)
我们也在考虑使 .qcow2 的最大大小 可配置。也许 64GiB 对于某些环境来说太大了,而且 较小的上限会有所帮助吗?
2019 年更新:自发布此答案以来,Docker for Mac 已经进行了许多更新以帮助缓解问题(特别是:支持不同的文件系统)。
尽管清理仍然不是全自动的,您可能需要不时进行修剪。有关有助于清理磁盘空间的单个命令,请参阅zhongjiajie's answer。
【讨论】:
这是答案。我的 .qcow2 高达 35Gb++! 非常感谢。我认为解决这个问题的唯一方法是经常清理这个文件。 @FrancoRabaglia 是的,我现在没有看到合适的解决方法,这将是计划修复的第一阶段:/ 如果我发现任何更新,我会将其编辑为答案。 我参考github.com/docker/for-mac/issues/371#issuecomment-315385246,然后输入docker run --rm --net=host --pid=host --privileged -it justincormack/nsenter1 /sbin/fstrim /var
,qcow2文件被收缩了。
Docker 桌面现在支持调整磁盘映像的大小。它实际上以不同的大小重新创建它,从而丢失了其中的所有内容,但它仍然有帮助。【参考方案6】:
docker container prune
docker system prune
docker image prune
docker volume prune
【讨论】:
这会做什么?请详细说明。 还有其他可能有帮助的修剪命令,可能应该添加到此答案中,包括docker image prune
和 docker volume prune
。【参考方案7】:
关于如何限制 docker 磁盘空间有几个选项,我将从限制/旋转日志开始:Docker container logs taking all my disk space
例如如果您有最新的 docker 版本,您可以在每个容器中使用 --log-opt max-size=50m
选项启动它。
另外 - 如果您有旧的、未使用的容器,您可以考虑查看位于 /var/lib/docker/containers/*/*-json.log
【讨论】:
这是一个 Mac 问题,不是 Linux 问题。【参考方案8】:由于这里没有什么对我有用,所以我就是这样做的。检查文件大小:
ls -lhks ~/Library/Containers/com.docker.docker//Data/vms/0/data/Docker.raw
然后在 docker 桌面简单地减小磁盘映像大小(我使用的是原始格式)。它会说它将删除所有内容,但是当您阅读这篇文章时,您可能已经拥有了。这样就创建了一个全新的空文件。
【讨论】:
【参考方案9】:$ sudo docker system prune
警告!这将删除:
所有停止的容器 至少一个容器未使用的所有网络 所有悬空图像 所有悬空构建缓存【讨论】:
以上是关于Docker 填满 macOS 上的存储空间的主要内容,如果未能解决你的问题,请参考以下文章
NODE.JS 如何在不填满存储空间的情况下保存 JSON 数据 [关闭]
全网最细Docker安装Minio,填满最新版大坑(强烈推荐收藏)
全网最细Docker安装Minio,填满最新版大坑(强烈推荐收藏)