github.com/gravitational/moby@v1.13.1/daemon/disk_usage.go (about) 1 package daemon 2 3 import ( 4 "fmt" 5 6 "github.com/Sirupsen/logrus" 7 "github.com/docker/distribution/digest" 8 "github.com/docker/docker/api/types" 9 "github.com/docker/docker/api/types/filters" 10 "github.com/docker/docker/layer" 11 "github.com/docker/docker/pkg/directory" 12 "github.com/docker/docker/volume" 13 ) 14 15 func (daemon *Daemon) getLayerRefs() map[layer.ChainID]int { 16 tmpImages := daemon.imageStore.Map() 17 layerRefs := map[layer.ChainID]int{} 18 for id, img := range tmpImages { 19 dgst := digest.Digest(id) 20 if len(daemon.referenceStore.References(dgst)) == 0 && len(daemon.imageStore.Children(id)) != 0 { 21 continue 22 } 23 24 rootFS := *img.RootFS 25 rootFS.DiffIDs = nil 26 for _, id := range img.RootFS.DiffIDs { 27 rootFS.Append(id) 28 chid := rootFS.ChainID() 29 layerRefs[chid]++ 30 } 31 } 32 33 return layerRefs 34 } 35 36 // SystemDiskUsage returns information about the daemon data disk usage 37 func (daemon *Daemon) SystemDiskUsage() (*types.DiskUsage, error) { 38 // Retrieve container list 39 allContainers, err := daemon.Containers(&types.ContainerListOptions{ 40 Size: true, 41 All: true, 42 }) 43 if err != nil { 44 return nil, fmt.Errorf("failed to retrieve container list: %v", err) 45 } 46 47 // Get all top images with extra attributes 48 allImages, err := daemon.Images(filters.NewArgs(), false, true) 49 if err != nil { 50 return nil, fmt.Errorf("failed to retrieve image list: %v", err) 51 } 52 53 // Get all local volumes 54 allVolumes := []*types.Volume{} 55 getLocalVols := func(v volume.Volume) error { 56 name := v.Name() 57 refs := daemon.volumes.Refs(v) 58 59 tv := volumeToAPIType(v) 60 sz, err := directory.Size(v.Path()) 61 if err != nil { 62 logrus.Warnf("failed to determine size of volume %v", name) 63 sz = -1 64 } 65 tv.UsageData = &types.VolumeUsageData{Size: sz, RefCount: int64(len(refs))} 66 allVolumes = append(allVolumes, tv) 67 68 return nil 69 } 70 71 err = daemon.traverseLocalVolumes(getLocalVols) 72 if err != nil { 73 return nil, err 74 } 75 76 // Get total layers size on disk 77 layerRefs := daemon.getLayerRefs() 78 allLayers := daemon.layerStore.Map() 79 var allLayersSize int64 80 for _, l := range allLayers { 81 size, err := l.DiffSize() 82 if err == nil { 83 if _, ok := layerRefs[l.ChainID()]; ok { 84 allLayersSize += size 85 } else { 86 logrus.Warnf("found leaked image layer %v", l.ChainID()) 87 } 88 } else { 89 logrus.Warnf("failed to get diff size for layer %v", l.ChainID()) 90 } 91 92 } 93 94 return &types.DiskUsage{ 95 LayersSize: allLayersSize, 96 Containers: allContainers, 97 Volumes: allVolumes, 98 Images: allImages, 99 }, nil 100 }