卓越飞翔博客卓越飞翔博客

卓越飞翔 - 您值得收藏的技术分享站
技术文章34915本站已运行393

`docker system df` 与 `/system/df` (docker api 端点)

`docker system df` 与 `/system/df` (docker api 端点)

php小编鱼仔在这里为大家介绍一下docker中的两个命令:`docker system df`和`/system/df`(docker api端点)。这两个命令都是用来查看docker系统资源使用情况的,但是它们的使用方式和结果展示方式略有不同。`docker system df`是一个docker命令,可以直接在终端中运行,它会显示出docker系统中各个资源(包括镜像、容器、数据卷等)的使用情况,以及总体的资源占用情况。而`/system/df`是一个docker api的端点,需要通过调用api来获取相关信息。它的返回结果与`docker system df`相似,但是更适合用于程序化的方式获取docker系统资源使用情况。

问题内容

我正在用 Go 编写一个程序,以从我的 docker 主机获取以 GB 为单位的总磁盘使用情况。为此,我使用 go lib 中的 func DiskUsage()

  • https://pkg.go.dev/github.com/docker/docker/client#Client.DiskUsage。

查看代码,该函数正在调用 docker api 端点 /system/df

  • https://docs.docker.com/engine/api/v1.43/#tag/System/operation/SystemDataUsage

但是,当我使用此库与使用命令 docker system df 计算 GB 时,我注意到一个奇怪的行为:

  • docker系统df输出:
    $ docker system df
    TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
    Images          223       4         21.02GB   20.7GB (98%)
    Containers      6         0         0B        0B
    Local Volumes   13        1         536.4MB   340.4MB (63%)
    Build Cache     954       0         13.51GB   13.51GB
    
  • My Go 应用程序输出:
    $ go run ./cmd/main.go
    Images: TOTAL (223), 17GB
    Build Cache: TOTAL (954), 29GB
    

正如您所看到的,两个输出之间存在差异。 我需要帮助来了解我从 /system/df 端点获取数据的计算是否有问题。谢谢:)

Go应用程序:

package main

import (
    "context"
    "fmt"

    "github.com/docker/docker/api/types"
    "github.com/docker/docker/client"
)

func main() {
    cli, err := client.NewClientWithOpts(client.FromEnv)
    if err != nil {
        panic(err)
    }

    diskUsg, err := cli.DiskUsage(context.Background(), types.DiskUsageOptions{})
    if err != nil {
        panic(err)
    }
    b := float64(0)
    for _, ch := range diskUsg.BuildCache {
        b = b + float64(ch.Size)
    }

    b2 := float64(0)
    for _, ch := range diskUsg.Images {
        if ch.Size > ch.SharedSize {
            b2 = b2 + (float64(ch.Size) - float64(ch.SharedSize))
            continue
        }
        b2 = b2 + (float64(ch.SharedSize) - float64(ch.Size))
    }

    fmt.Printf("Images: TOTAL (%d), %2.fGBn", len(diskUsg.Images), float64(b2)/(1<<30))
    fmt.Printf("Build Cache: TOTAL (%d), %2.fGBn", len(diskUsg.BuildCache), float64(b)/(1<<30))
}

解决方法

基于Docker源代码:

  • system df 命令:https:/ /github.com/docker/cli/blob/v24.0.5/cli/command/system/df.go
  • 输出格式:https:// github.com/docker/cli/blob/v24.0.5/cli/command/formatter/disk_usage.go

您应该能够使用以下代码准确重现 docker 系统 df 所做的事情:

  • go.mod
module 76982562-docker-system-df-vs-system-df-docker-api-endpoint

go 1.21.0

require (
    github.com/docker/cli v24.0.5+incompatible
    github.com/docker/docker v24.0.5+incompatible
)
  • main.go
package main

import (
    "context"
    "fmt"
    "os"

    "github.com/docker/cli/cli/command/formatter"
    "github.com/docker/docker/api/types"
    "github.com/docker/docker/client"
    "github.com/docker/go-units"
)

func main() {
    cli, err := client.NewClientWithOpts(client.FromEnv)
    if err != nil {
        panic(err)
    }

    diskUsage, err := cli.DiskUsage(context.Background(), types.DiskUsageOptions{})
    if err != nil {
        panic(err)
    }

    var bsz int64
    for _, bc := range diskUsage.BuildCache {
        if !bc.Shared {
            bsz += bc.Size
        }
    }

    fmt.Printf("Images: TOTAL (%d), %sn", len(diskUsage.Images), units.HumanSize(float64(diskUsage.LayersSize)))
    fmt.Printf("Build Cache: TOTAL (%d), %sn", len(diskUsage.BuildCache), units.HumanSize(float64(bsz)))
}
  • 对于图片,docker库直接提供了diskUsage.LayersSize来表示总大小,所以你不用自己计算
  • 对于构建缓存,您需要排除共享项目 (if !bc.Shared)

要以正确的单位转换大小,我强烈建议使用 github.com/docker/go-units (例如 units.HumanSize(float64(diskUsage.LayersSize)))。这将避免您单位转换的噩梦!

卓越飞翔博客
上一篇: Go - 错误。无法解包自定义错误类型
下一篇: 返回列表
留言与评论(共有 0 条评论)
   
验证码:
隐藏边栏