Home >Backend Development >Golang >`docker system df` and `/system/df` (docker api endpoint)

`docker system df` and `/system/df` (docker api endpoint)

WBOY
WBOYforward
2024-02-09 16:45:08567browse

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

php editor Yuzai is here to introduce to you two commands in docker: `docker system df` and `/system/df` (docker api endpoint). Both commands are used to view the docker system resource usage, but their usage and result display methods are slightly different. `docker system df` is a docker command that can be run directly in the terminal. It will display the usage of various resources in the docker system (including images, containers, data volumes, etc.), as well as the overall resource usage. And `/system/df` is a docker API endpoint, and you need to obtain relevant information by calling the API. Its return result is similar to `docker system df`, but it is more suitable for programmatically obtaining docker system resource usage.

Question content

I am writing a program in Go to get the total disk usage in GB from my docker host. For this I use func DiskUsage() from go lib:

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

View the code, the function is calling the docker api endpoint /system/df:

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

However, when I use this library with the calculation of GB using the command docker system df, I notice a strange behavior:

  • docker system dfOutput:
    $ 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 application output:
    $ go run ./cmd/main.go
    Images: TOTAL (223), 17GB
    Build Cache: TOTAL (954), 29GB
    

As you can see, there is a difference between the two outputs. I need help understanding if there is something wrong with my calculations that get the data from the /system/df endpoint. Thanks:)

Go Application:

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.fGB\n", len(diskUsg.Images), float64(b2)/(1<<30))
    fmt.Printf("Build Cache: TOTAL (%d), %2.fGB\n", len(diskUsg.BuildCache), float64(b)/(1<<30))
}

Solution

Based on Docker source code:

You should be able to reproduce exactly what docker system df does using the following code:

  • 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
<code>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), %s\n", len(diskUsage.Images), units.HumanSize(float64(diskUsage.LayersSize)))
    fmt.Printf("Build Cache: TOTAL (%d), %s\n", len(diskUsage.BuildCache), units.HumanSize(float64(bsz)))
}
</code>
  • For images, the docker library directly provides diskUsage.LayersSize to represent the total size, so you don’t have to calculate it yourself
  • For the build cache you need to exclude shared projects (if !bc.Shared)

To convert the size in the correct units, I strongly recommend using github.com/docker/go-units (e.g. units.HumanSize(float64(diskUsage.LayersSize))) . This will save you the unit conversion nightmare!

The above is the detailed content of `docker system df` and `/system/df` (docker api endpoint). For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete