【问题标题】:Docker filling up storage on macOSDocker 填满 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

【问题讨论】:

    标签: macos docker containers dockerfile diskspace


    【解决方案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 命令(或DISCARDUNMAP)允许文件系统向磁盘发出信号,告知磁盘范围内的扇区包含陈旧数据并且可以将其遗忘。这允许:

      • 一个 SSD 驱动器,用于擦除和重复使用空间,而不是花时间在四处移动它;和
      • Docker for Mac 释放主机文件系统中的块,压缩文件。

      那么我们如何做到这一点呢?

      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
      vpnkit-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 prunedocker volume prune
        【解决方案7】:

        关于如何限制 docker 磁盘空间有几个选项,我将从限制/旋转日志开始:Docker container logs taking all my disk space

        例如如果您有最新的 docker 版本,您可以在每个容器中使用 --log-opt max-size=50m 选项启动它。 另外 - 如果您有旧的、未使用的容器,您可以考虑查看位于 /var/lib/docker/containers/*/*-json.log

        的 docker 日志

        【讨论】:

        • 这是一个 Mac 问题,不是 Linux 问题。
        【解决方案8】:

        由于这里没有什么对我有用,所以我就是这样做的。检查文件大小:

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

        然后在 docker 桌面简单地减小磁盘映像大小(我使用的是原始格式)。它会说它将删除所有内容,但是当您阅读这篇文章时,您可能已经拥有了。这样就创建了一个全新的空文件。

        【讨论】:

          【解决方案9】:
          $ sudo docker system prune
          

          警告!这将删除:

          • 所有停止的容器
          • 至少一个容器未使用的所有网络
          • 所有悬空图像
          • 所有悬空构建缓存

          【讨论】:

            猜你喜欢
            • 2017-11-19
            • 1970-01-01
            • 2021-06-28
            • 2021-08-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-06-09
            • 1970-01-01
            相关资源
            最近更新 更多