github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/daemon/images/service.go (about) 1 package images // import "github.com/docker/docker/daemon/images" 2 3 import ( 4 "context" 5 "os" 6 7 "github.com/containerd/containerd/content" 8 "github.com/containerd/containerd/leases" 9 "github.com/docker/docker/api/types" 10 "github.com/docker/docker/api/types/filters" 11 "github.com/docker/docker/container" 12 daemonevents "github.com/docker/docker/daemon/events" 13 "github.com/docker/docker/distribution/metadata" 14 "github.com/docker/docker/distribution/xfer" 15 "github.com/docker/docker/image" 16 "github.com/docker/docker/layer" 17 dockerreference "github.com/docker/docker/reference" 18 "github.com/docker/docker/registry" 19 "github.com/docker/libtrust" 20 "github.com/opencontainers/go-digest" 21 "github.com/pkg/errors" 22 "golang.org/x/sync/singleflight" 23 ) 24 25 type containerStore interface { 26 // First is used by image delete 27 First(container.StoreFilter) *container.Container 28 // List is used by image prune, and image list 29 List() []*container.Container 30 // Get is used by CommitBuildStep 31 // TODO: remove, only used for CommitBuildStep 32 Get(string) *container.Container 33 } 34 35 // ImageServiceConfig is the configuration used to create a new ImageService 36 type ImageServiceConfig struct { 37 ContainerStore containerStore 38 DistributionMetadataStore metadata.Store 39 EventsService *daemonevents.Events 40 ImageStore image.Store 41 LayerStore layer.Store 42 MaxConcurrentDownloads int 43 MaxConcurrentUploads int 44 MaxDownloadAttempts int 45 ReferenceStore dockerreference.Store 46 RegistryService registry.Service 47 TrustKey libtrust.PrivateKey 48 ContentStore content.Store 49 Leases leases.Manager 50 ContentNamespace string 51 } 52 53 // NewImageService returns a new ImageService from a configuration 54 func NewImageService(config ImageServiceConfig) *ImageService { 55 return &ImageService{ 56 containers: config.ContainerStore, 57 distributionMetadataStore: config.DistributionMetadataStore, 58 downloadManager: xfer.NewLayerDownloadManager(config.LayerStore, config.MaxConcurrentDownloads, xfer.WithMaxDownloadAttempts(config.MaxDownloadAttempts)), 59 eventsService: config.EventsService, 60 imageStore: &imageStoreWithLease{Store: config.ImageStore, leases: config.Leases, ns: config.ContentNamespace}, 61 layerStore: config.LayerStore, 62 referenceStore: config.ReferenceStore, 63 registryService: config.RegistryService, 64 trustKey: config.TrustKey, 65 uploadManager: xfer.NewLayerUploadManager(config.MaxConcurrentUploads), 66 leases: config.Leases, 67 content: config.ContentStore, 68 contentNamespace: config.ContentNamespace, 69 } 70 } 71 72 // ImageService provides a backend for image management 73 type ImageService struct { 74 containers containerStore 75 distributionMetadataStore metadata.Store 76 downloadManager *xfer.LayerDownloadManager 77 eventsService *daemonevents.Events 78 imageStore image.Store 79 layerStore layer.Store 80 pruneRunning int32 81 referenceStore dockerreference.Store 82 registryService registry.Service 83 trustKey libtrust.PrivateKey 84 uploadManager *xfer.LayerUploadManager 85 leases leases.Manager 86 content content.Store 87 contentNamespace string 88 usage singleflight.Group 89 } 90 91 // DistributionServices provides daemon image storage services 92 type DistributionServices struct { 93 DownloadManager *xfer.LayerDownloadManager 94 V2MetadataService metadata.V2MetadataService 95 LayerStore layer.Store 96 ImageStore image.Store 97 ReferenceStore dockerreference.Store 98 } 99 100 // DistributionServices return services controlling daemon image storage 101 func (i *ImageService) DistributionServices() DistributionServices { 102 return DistributionServices{ 103 DownloadManager: i.downloadManager, 104 V2MetadataService: metadata.NewV2MetadataService(i.distributionMetadataStore), 105 LayerStore: i.layerStore, 106 ImageStore: i.imageStore, 107 ReferenceStore: i.referenceStore, 108 } 109 } 110 111 // CountImages returns the number of images stored by ImageService 112 // called from info.go 113 func (i *ImageService) CountImages() int { 114 return i.imageStore.Len() 115 } 116 117 // Children returns the children image.IDs for a parent image. 118 // called from list.go to filter containers 119 // TODO: refactor to expose an ancestry for image.ID? 120 func (i *ImageService) Children(id image.ID) []image.ID { 121 return i.imageStore.Children(id) 122 } 123 124 // CreateLayer creates a filesystem layer for a container. 125 // called from create.go 126 // TODO: accept an opt struct instead of container? 127 func (i *ImageService) CreateLayer(container *container.Container, initFunc layer.MountInit) (layer.RWLayer, error) { 128 var layerID layer.ChainID 129 if container.ImageID != "" { 130 img, err := i.imageStore.Get(container.ImageID) 131 if err != nil { 132 return nil, err 133 } 134 layerID = img.RootFS.ChainID() 135 } 136 137 rwLayerOpts := &layer.CreateRWLayerOpts{ 138 MountLabel: container.MountLabel, 139 InitFunc: initFunc, 140 StorageOpt: container.HostConfig.StorageOpt, 141 } 142 143 return i.layerStore.CreateRWLayer(container.ID, layerID, rwLayerOpts) 144 } 145 146 // GetLayerByID returns a layer by ID 147 // called from daemon.go Daemon.restore(), and Daemon.containerExport(). 148 func (i *ImageService) GetLayerByID(cid string) (layer.RWLayer, error) { 149 return i.layerStore.GetRWLayer(cid) 150 } 151 152 // LayerStoreStatus returns the status for each layer store 153 // called from info.go 154 func (i *ImageService) LayerStoreStatus() [][2]string { 155 return i.layerStore.DriverStatus() 156 } 157 158 // GetLayerMountID returns the mount ID for a layer 159 // called from daemon.go Daemon.Shutdown(), and Daemon.Cleanup() (cleanup is actually continerCleanup) 160 // TODO: needs to be refactored to Unmount (see callers), or removed and replaced with GetLayerByID 161 func (i *ImageService) GetLayerMountID(cid string) (string, error) { 162 return i.layerStore.GetMountID(cid) 163 } 164 165 // Cleanup resources before the process is shutdown. 166 // called from daemon.go Daemon.Shutdown() 167 func (i *ImageService) Cleanup() error { 168 if err := i.layerStore.Cleanup(); err != nil { 169 return errors.Wrap(err, "error during layerStore.Cleanup()") 170 } 171 return nil 172 } 173 174 // StorageDriver returns the name of the storage driver used by the ImageService. 175 func (i *ImageService) StorageDriver() string { 176 return i.layerStore.DriverName() 177 } 178 179 // ReleaseLayer releases a layer allowing it to be removed 180 // called from delete.go Daemon.cleanupContainer(), and Daemon.containerExport() 181 func (i *ImageService) ReleaseLayer(rwlayer layer.RWLayer) error { 182 metaData, err := i.layerStore.ReleaseRWLayer(rwlayer) 183 layer.LogReleaseMetadata(metaData) 184 if err != nil && !errors.Is(err, layer.ErrMountDoesNotExist) && !errors.Is(err, os.ErrNotExist) { 185 return errors.Wrapf(err, "driver %q failed to remove root filesystem", 186 i.layerStore.DriverName()) 187 } 188 return nil 189 } 190 191 // LayerDiskUsage returns the number of bytes used by layer stores 192 // called from disk_usage.go 193 func (i *ImageService) LayerDiskUsage(ctx context.Context) (int64, error) { 194 ch := i.usage.DoChan("LayerDiskUsage", func() (interface{}, error) { 195 var allLayersSize int64 196 layerRefs := i.getLayerRefs() 197 allLayers := i.layerStore.Map() 198 for _, l := range allLayers { 199 select { 200 case <-ctx.Done(): 201 return allLayersSize, ctx.Err() 202 default: 203 size := l.DiffSize() 204 if _, ok := layerRefs[l.ChainID()]; ok { 205 allLayersSize += size 206 } 207 } 208 } 209 return allLayersSize, nil 210 }) 211 select { 212 case <-ctx.Done(): 213 return 0, ctx.Err() 214 case res := <-ch: 215 if res.Err != nil { 216 return 0, res.Err 217 } 218 return res.Val.(int64), nil 219 } 220 } 221 222 func (i *ImageService) getLayerRefs() map[layer.ChainID]int { 223 tmpImages := i.imageStore.Map() 224 layerRefs := map[layer.ChainID]int{} 225 for id, img := range tmpImages { 226 dgst := digest.Digest(id) 227 if len(i.referenceStore.References(dgst)) == 0 && len(i.imageStore.Children(id)) != 0 { 228 continue 229 } 230 231 rootFS := *img.RootFS 232 rootFS.DiffIDs = nil 233 for _, id := range img.RootFS.DiffIDs { 234 rootFS.Append(id) 235 chid := rootFS.ChainID() 236 layerRefs[chid]++ 237 } 238 } 239 240 return layerRefs 241 } 242 243 // ImageDiskUsage returns information about image data disk usage. 244 func (i *ImageService) ImageDiskUsage(ctx context.Context) ([]*types.ImageSummary, error) { 245 ch := i.usage.DoChan("ImageDiskUsage", func() (interface{}, error) { 246 // Get all top images with extra attributes 247 imgs, err := i.Images(ctx, types.ImageListOptions{ 248 Filters: filters.NewArgs(), 249 SharedSize: true, 250 ContainerCount: true, 251 }) 252 if err != nil { 253 return nil, errors.Wrap(err, "failed to retrieve image list") 254 } 255 return imgs, nil 256 }) 257 select { 258 case <-ctx.Done(): 259 return nil, ctx.Err() 260 case res := <-ch: 261 if res.Err != nil { 262 return nil, res.Err 263 } 264 return res.Val.([]*types.ImageSummary), nil 265 } 266 } 267 268 // UpdateConfig values 269 // 270 // called from reload.go 271 func (i *ImageService) UpdateConfig(maxDownloads, maxUploads int) { 272 if i.downloadManager != nil && maxDownloads != 0 { 273 i.downloadManager.SetConcurrency(maxDownloads) 274 } 275 if i.uploadManager != nil && maxUploads != 0 { 276 i.uploadManager.SetConcurrency(maxUploads) 277 } 278 }