【问题标题】:How to analyze disk usage of a Docker container如何分析 Docker 容器的磁盘使用情况
【发布时间】:2015-01-01 09:39:12
【问题描述】:

我可以看到 Docker 占用了我的文件系统的 12GB:

2.7G    /var/lib/docker/vfs/dir
2.7G    /var/lib/docker/vfs
2.8G    /var/lib/docker/devicemapper/mnt
6.3G    /var/lib/docker/devicemapper/devicemapper
9.1G    /var/lib/docker/devicemapper
12G     /var/lib/docker

但是,我怎么知道它是如何分布在容器中的?

我尝试通过运行(新的 v1.3 命令)附加到容器

docker exec -it <container_name> bash

然后运行“df -h”来分析磁盘使用情况。它似乎有效,但不适用于使用“volumes-from”的容器。

例如,我为 MongoDB 使用了一个纯数据容器,称为“mongo-data”。

当我在容器内运行docker run -it --volumes-from mongo-data busybox,然后运行df -h 时,它说安装在/data/db(我的“mongo-data”数据专用容器)上的文件系统使用11.3G,但是当我这样做时@ 987654328@,说只用了2.1G。

那么,如何分析容器/卷的磁盘使用情况?或者,就我而言,如何找出“mongo-data”容器的大小?

【问题讨论】:

标签: mongodb docker docker-container lxc device-mapper


【解决方案1】:

这是最简单的方法

docker ps -s

【讨论】:

    【解决方案2】:

    替代 docker ps --size

    由于“docker ps --size”会在主机上产生沉重的 IO 负载,因此在生产环境中每分钟运行这样的命令是不可行的。因此,我们必须采取一种变通方法来获得所需的容器大小,或者更准确地说,RW 层的大小对系统性能的影响较小。

    这种方法收集每个容器的“设备名称”,然后使用“df”命令检查它的大小。这些“设备名称”是安装在每个容器上的精简配置卷。一个问题仍然存在,因为这个观察到的大小也意味着底层图像的所有只读层。为了解决这个问题,我们可以简单地检查使用的容器镜像的大小,然后从设备/瘦卷的大小中减去它。

    应该注意,在使用设备映射器时,每个图像层都被实现为一种 lvm 快照。不幸的是,我无法让我的 rhel 系统打印出这些快照/图层。否则,我们可以简单地收集“最新”快照的大小。如果有人能把事情说清楚,那就太好了。不过……

    经过一些测试,似乎创建一个容器总是会增加大约 100 的开销。 40MiB(使用基于镜像“httpd:2.4.46-alpine”的容器测试):

    1. docker run -d --name apache httpd:2.4.46-alpine // 现在从 docker inspect 获取设备名称并使用 df 查找它
    2. df -T -> 90MB 而“docker ps --size”中的“虚拟大小”表示 50MB 和 2Bytes 的非常小的有效负载 -> 神秘的开销 40MB
    3. 在容器内卷曲/下载 100MB 文件
    4. df -T -> 190MB 而“docker ps --size”中的“虚拟大小”状态为 150MB,有效负载为 100MB -> 开销 40MB

    以下 shell 打印与“docker ps --size”结果匹配的结果(以字节为单位)(但请记住提到的 40MB 开销)

    for c in  $(docker ps -q); do \
    container_name=$(docker inspect -f "{{.Name}}" ${c} | sed 's/^\///g' ); \
    device_n=$(docker inspect -f "{{.GraphDriver.Data.DeviceName}}" ${c} | sed 's/.*-//g'); \
    device_size_kib=$(df -T | grep ${device_n} | awk '{print $4}'); \
    device_size_byte=$((1024 * ${device_size_kib})); \
    image_sha=$(docker inspect -f "{{.Image}}" ${c} | sed 's/.*://g' ); \
    image_size_byte=$(docker image inspect -f "{{.Size}}" ${image_sha}); \
    container_size_byte=$((${device_size_byte} - ${image_size_byte})); \
    \
    echo my_node_dm_device_size_bytes\{cname=\"${container_name}\"\} ${device_size_byte}; \
    echo my_node_dm_container_size_bytes\{cname=\"${container_name}\"\} ${container_size_byte}; \
    echo my_node_dm_image_size_bytes\{cname=\"${container_name}\"\} ${image_size_byte}; \
    done
    

    关于设备映射器的进一步阅读:https://test-dockerrr.readthedocs.io/en/latest/userguide/storagedriver/device-mapper-driver/

    【讨论】:

      【解决方案3】:

      改进 Maxime 的回答器:

      docker ps --size

      你会看到这样的东西:

      +---------------+---------------+--------------------+
      | CONTAINER ID  | IMAGE         | SIZE               |
      +===============+===============+====================+
      | 6ca0cef8db8d  | nginx         | 2B (virtual 183MB) |
      | 3ab1a4d8dc5a  | nginx         | 5B (virtual 183MB) |
      +---------------+---------------+--------------------+
      

      启动容器时,启动容器的镜像以只读方式挂载(虚拟)
      最重要的是,挂载了一个可写层,对容器所做的任何更改都会写入其中。

      因此,虚拟大小(示例中为 183MB)只使用一次,无论从同一个映像启动多少个容器 - 我可以启动 1 个容器或 1000 个容器; 不使用额外的磁盘空间
      但是,每个容器的“大小”(示例中为 2B)是唯一的,因此磁盘上使用的总空间为:

      183MB + 5B + 2B

      请注意,显示的大小不包括用于容器的所有磁盘空间。
      目前不包括的东西是;
      - 卷
      - 交换
      - 检查点
      - 用于容器生成的日志文件的磁盘空间

      https://github.com/docker/docker.github.io/issues/1520#issuecomment-305179362

      【讨论】:

      • 那么如果说size为0,那是否意味着可写层没有变化?
      • 我不能确定,也许对文本文件的最小更改会导致 0
      • 有分析图像的工具,可以导出到tar.gz,解压,然后使用比较器
      【解决方案4】:

      1.13.0 之后,Docker 包含一个新命令 docker system df 来显示 docker 磁盘使用情况。

      $ docker system df
      TYPE            TOTAL        ACTIVE     SIZE        RECLAIMABLE
      Images          5            1          2.777 GB    2.647 GB (95%)
      Containers      1            1          0 B         0B
      Local Volumes   4            1          3.207 GB    2.261 (70%)
      

      要显示有关空间使用的更多详细信息:

      $ docker system df --verbose
      

      【讨论】:

      • 如果你有很多组件,一个有用的命令:docker system df --verbose &gt; docker.stats-2019-07-18.log
      • 容器的 SIZE 列是什么意思?我关闭了一些容器,例如,此命令显示 SIZE = 100MB。
      • SIZE=100MB 关闭容器
      【解决方案5】:

      要查看容器的文件大小,可以使用docker ps--size 参数:

      docker ps --size
      

      【讨论】:

      【解决方案6】:

      我使用docker stats $(docker ps --format={{.Names}}) --no-stream 获取:

      1. CPU 使用率,
      2. 内存使用量/分配给容器的内存总量(可以通过 docker run 命令分配)
      3. 内存百分比
      4. 块 I/O
      5. 网络 I/O

      【讨论】:

        【解决方案7】:

        请记住,docker ps --size 可能是一个昂贵的命令,需要几分钟才能完成。这同样适用于带有size=1 的容器列表 API 请求。最好不要太频繁地运行它。

        看看我们编译的alternatives,包括docker持久卷目录的du -hs选项。

        【讨论】:

        • 在我的服务器上并非如此 - 以毫秒为单位运行。 YMMV 对上述内容的警告(测试,正如 Sergei 所说的“......可能......”)
        • 我也在测试,使用 docker ps --size 还是可以接受的
        【解决方案8】:

        你可以使用

        docker history IMAGE_ID
        

        查看图像大小在其各个子组件之间的分布情况。

        【讨论】:

          【解决方案9】:

          发布这个作为答案是因为我上面的 cmets 被隐藏了:

          列出容器的大小:

          du -d 2 -h /var/lib/docker/devicemapper | grep `docker inspect -f "{{.Id}}" <container_name>`
          

          列出容器卷的大小:

          docker inspect -f "{{.Volumes}}" <container_name> | sed 's/map\[//' | sed 's/]//' | tr ' ' '\n' | sed 's/.*://' | xargs sudo du -d 1 -h
          

          编辑: 列出所有正在运行的容器的大小和体积:

          for d in `docker ps -q`; do
              d_name=`docker inspect -f {{.Name}} $d`
              echo "========================================================="
              echo "$d_name ($d) container size:"
              sudo du -d 2 -h /var/lib/docker/devicemapper | grep `docker inspect -f "{{.Id}}" $d`
              echo "$d_name ($d) volumes:"
              docker inspect -f "{{.Volumes}}" $d | sed 's/map\[//' | sed 's/]//' | tr ' ' '\n' | sed 's/.*://' | xargs sudo du -d 1 -h
          done
          

          注意:根据您的 Docker 文件系统更改“devicemapper”(例如“aufs”)

          【讨论】:

          • "du -d 2" 在我的 Centos 系统上不起作用,我不得不改用 "du --max-depth 2"。
          • 在 Mac 上显示/var/lib/docker/devicemapper: No such file or directory。知道 devicemapper 在 mac 上的存储位置吗?
          • Markus:如果你使用 boot2docker,你必须在你的 boot2docker 主机虚拟机中运行du 命令。如果您使用 aufs 而不是设备映射器,该命令也可能会失败。
          • 使用 'docker ps -q' 来列出容器的哈希值而不是 awk/tail 怎么样?
          • 在我的 Ubuntu 14.04/Docker 1.10.2 安装中,容器大小始终为空白。
          【解决方案10】:

          音量部分不再起作用,所以如果有人感兴趣,我只是稍微更改一下上面的脚本:

          for d in `docker ps | awk '{print $1}' | tail -n +2`; do
              d_name=`docker inspect -f {{.Name}} $d`
              echo "========================================================="
              echo "$d_name ($d) container size:"
              sudo du -d 2 -h /var/lib/docker/aufs | grep `docker inspect -f "{{.Id}}" $d`
              echo "$d_name ($d) volumes:"
              for mount in `docker inspect -f "{{range .Mounts}} {{.Source}}:{{.Destination}}                                                                                                                                                      
              {{end}}" $d`; do
                  size=`echo $mount | cut -d':' -f1 | sudo xargs du -d 0 -h`
                  mnt=`echo $mount | cut -d':' -f2`
                  echo "$size mounted on $mnt"
              done
          done
          

          【讨论】:

          • 安装点!= 体积
          • Mac Docker 1.12.1 将图像文件放入 ~/Library/Containers/com.docker.docker/ 而不是 /var/lib/docker/aufs。不包含 .Id 或 .Name 的文件名:-(
          【解决方案11】:

          (这个答案没有用,但由于某些 cmets 可能有用,所以将其留在这里)

          docker images 将显示“虚拟大小”,即包括所有较低层在内的总大小。因此,如果您的容器共享相同的基本映像,则需要进行重复计算。

          documentation

          【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-05-28
          • 2022-06-13
          • 1970-01-01
          • 2020-10-08
          • 1970-01-01
          • 2019-04-19
          • 1970-01-01
          • 2019-08-10
          相关资源
          最近更新 更多