implement docker system df

Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
Nicolas De Loof 2022-09-01 10:30:34 +02:00
parent 5dd50a381a
commit 8d0dc69027
No known key found for this signature in database
GPG Key ID: 9858809D6F8F6E7E
3 changed files with 52 additions and 8 deletions

View File

@ -116,7 +116,7 @@ func (s *systemRouter) getDiskUsage(ctx context.Context, w http.ResponseWriter,
var getContainers, getImages, getVolumes, getBuildCache bool var getContainers, getImages, getVolumes, getBuildCache bool
typeStrs, ok := r.Form["type"] typeStrs, ok := r.Form["type"]
if versions.LessThan(version, "1.42") || !ok { if versions.LessThan(version, "1.42") || !ok {
getContainers, getImages, getVolumes, getBuildCache = true, true, true, true getContainers, getImages, getVolumes, getBuildCache = true, true, true, s.builder != nil
} else { } else {
for _, typ := range typeStrs { for _, typ := range typeStrs {
switch types.DiskUsageObject(typ) { switch types.DiskUsageObject(typ) {

View File

@ -2,22 +2,26 @@ package containerd
import ( import (
"context" "context"
"errors"
"github.com/containerd/containerd" "github.com/containerd/containerd"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/snapshots"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/container" "github.com/docker/docker/container"
"github.com/docker/docker/daemon/images" "github.com/docker/docker/daemon/images"
"github.com/docker/docker/errdefs" "github.com/docker/docker/errdefs"
"github.com/docker/docker/image" "github.com/docker/docker/image"
"github.com/docker/docker/layer" "github.com/docker/docker/layer"
"github.com/pkg/errors"
"golang.org/x/sync/singleflight"
) )
// ImageService implements daemon.ImageService // ImageService implements daemon.ImageService
type ImageService struct { type ImageService struct {
client *containerd.Client client *containerd.Client
snapshotter string snapshotter string
usage singleflight.Group
} }
// NewService creates a new ImageService. // NewService creates a new ImageService.
@ -101,12 +105,53 @@ func (i *ImageService) ReleaseLayer(rwlayer layer.RWLayer) error {
// LayerDiskUsage returns the number of bytes used by layer stores // LayerDiskUsage returns the number of bytes used by layer stores
// called from disk_usage.go // called from disk_usage.go
func (i *ImageService) LayerDiskUsage(ctx context.Context) (int64, error) { func (i *ImageService) LayerDiskUsage(ctx context.Context) (int64, error) {
return 0, errdefs.NotImplemented(errors.New("not implemented")) ch := i.usage.DoChan("LayerDiskUsage", func() (interface{}, error) {
var allLayersSize int64
snapshotter := i.client.SnapshotService(i.snapshotter)
snapshotter.Walk(ctx, func(ctx context.Context, info snapshots.Info) error {
usage, err := snapshotter.Usage(ctx, info.Name)
if err != nil {
return err
}
allLayersSize += usage.Size
return nil
})
return allLayersSize, nil
})
select {
case <-ctx.Done():
return 0, ctx.Err()
case res := <-ch:
if res.Err != nil {
return 0, res.Err
}
return res.Val.(int64), nil
}
} }
// ImageDiskUsage returns information about image data disk usage. // ImageDiskUsage returns information about image data disk usage.
func (i *ImageService) ImageDiskUsage(ctx context.Context) ([]*types.ImageSummary, error) { func (i *ImageService) ImageDiskUsage(ctx context.Context) ([]*types.ImageSummary, error) {
return nil, errdefs.NotImplemented(errors.New("not implemented")) ch := i.usage.DoChan("ImageDiskUsage", func() (interface{}, error) {
// Get all top images with extra attributes
imgs, err := i.Images(ctx, types.ImageListOptions{
Filters: filters.NewArgs(),
SharedSize: true,
ContainerCount: true,
})
if err != nil {
return nil, errors.Wrap(err, "failed to retrieve image list")
}
return imgs, nil
})
select {
case <-ctx.Done():
return nil, ctx.Err()
case res := <-ch:
if res.Err != nil {
return nil, res.Err
}
return res.Val.([]*types.ImageSummary), nil
}
} }
// UpdateConfig values // UpdateConfig values

View File

@ -2,7 +2,6 @@ package images // import "github.com/docker/docker/daemon/images"
import ( import (
"context" "context"
"fmt"
"os" "os"
"github.com/containerd/containerd/content" "github.com/containerd/containerd/content"
@ -245,15 +244,15 @@ func (i *ImageService) getLayerRefs() map[layer.ChainID]int {
func (i *ImageService) ImageDiskUsage(ctx context.Context) ([]*types.ImageSummary, error) { func (i *ImageService) ImageDiskUsage(ctx context.Context) ([]*types.ImageSummary, error) {
ch := i.usage.DoChan("ImageDiskUsage", func() (interface{}, error) { ch := i.usage.DoChan("ImageDiskUsage", func() (interface{}, error) {
// Get all top images with extra attributes // Get all top images with extra attributes
images, err := i.Images(ctx, types.ImageListOptions{ imgs, err := i.Images(ctx, types.ImageListOptions{
Filters: filters.NewArgs(), Filters: filters.NewArgs(),
SharedSize: true, SharedSize: true,
ContainerCount: true, ContainerCount: true,
}) })
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to retrieve image list: %v", err) return nil, errors.Wrap(err, "failed to retrieve image list")
} }
return images, nil return imgs, nil
}) })
select { select {
case <-ctx.Done(): case <-ctx.Done():