github.com/jfrazelle/docker@v1.1.2-0.20210712172922-bf78e25fe508/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/container" 10 daemonevents "github.com/docker/docker/daemon/events" 11 "github.com/docker/docker/distribution" 12 "github.com/docker/docker/distribution/metadata" 13 "github.com/docker/docker/distribution/xfer" 14 "github.com/docker/docker/image" 15 "github.com/docker/docker/layer" 16 dockerreference "github.com/docker/docker/reference" 17 "github.com/docker/docker/registry" 18 "github.com/docker/libtrust" 19 digest "github.com/opencontainers/go-digest" 20 "github.com/pkg/errors" 21 "github.com/sirupsen/logrus" 22 ) 23 24 type containerStore interface { 25 // used by image delete 26 First(container.StoreFilter) *container.Container 27 // used by image prune, and image list 28 List() []*container.Container 29 // TODO: remove, only used for CommitBuildStep 30 Get(string) *container.Container 31 } 32 33 // ImageServiceConfig is the configuration used to create a new ImageService 34 type ImageServiceConfig struct { 35 ContainerStore containerStore 36 DistributionMetadataStore metadata.Store 37 EventsService *daemonevents.Events 38 ImageStore image.Store 39 LayerStore layer.Store 40 MaxConcurrentDownloads int 41 MaxConcurrentUploads int 42 MaxDownloadAttempts int 43 ReferenceStore dockerreference.Store 44 RegistryService registry.Service 45 TrustKey libtrust.PrivateKey 46 ContentStore content.Store 47 Leases leases.Manager 48 ContentNamespace string 49 } 50 51 // NewImageService returns a new ImageService from a configuration 52 func NewImageService(config ImageServiceConfig) *ImageService { 53 logrus.Debugf("Max Concurrent Downloads: %d", config.MaxConcurrentDownloads) 54 logrus.Debugf("Max Concurrent Uploads: %d", config.MaxConcurrentUploads) 55 logrus.Debugf("Max Download Attempts: %d", config.MaxDownloadAttempts) 56 return &ImageService{ 57 containers: config.ContainerStore, 58 distributionMetadataStore: config.DistributionMetadataStore, 59 downloadManager: xfer.NewLayerDownloadManager(config.LayerStore, config.MaxConcurrentDownloads, xfer.WithMaxDownloadAttempts(config.MaxDownloadAttempts)), 60 eventsService: config.EventsService, 61 imageStore: &imageStoreWithLease{Store: config.ImageStore, leases: config.Leases, ns: config.ContentNamespace}, 62 layerStore: config.LayerStore, 63 referenceStore: config.ReferenceStore, 64 registryService: config.RegistryService, 65 trustKey: config.TrustKey, 66 uploadManager: xfer.NewLayerUploadManager(config.MaxConcurrentUploads), 67 leases: config.Leases, 68 content: config.ContentStore, 69 contentNamespace: config.ContentNamespace, 70 } 71 } 72 73 // ImageService provides a backend for image management 74 type ImageService struct { 75 containers containerStore 76 distributionMetadataStore metadata.Store 77 downloadManager *xfer.LayerDownloadManager 78 eventsService *daemonevents.Events 79 imageStore image.Store 80 layerStore layer.Store 81 pruneRunning int32 82 referenceStore dockerreference.Store 83 registryService registry.Service 84 trustKey libtrust.PrivateKey 85 uploadManager *xfer.LayerUploadManager 86 leases leases.Manager 87 content content.Store 88 contentNamespace string 89 } 90 91 // DistributionServices provides daemon image storage services 92 type DistributionServices struct { 93 DownloadManager distribution.RootFSDownloadManager 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 // Indexing by OS is safe here as validation of OS has already been performed in create() (the only 144 // caller), and guaranteed non-nil 145 return i.layerStore.CreateRWLayer(container.ID, layerID, rwLayerOpts) 146 } 147 148 // GetLayerByID returns a layer by ID 149 // called from daemon.go Daemon.restore(), and Daemon.containerExport() 150 func (i *ImageService) GetLayerByID(cid string) (layer.RWLayer, error) { 151 return i.layerStore.GetRWLayer(cid) 152 } 153 154 // LayerStoreStatus returns the status for each layer store 155 // called from info.go 156 func (i *ImageService) LayerStoreStatus() [][2]string { 157 return i.layerStore.DriverStatus() 158 } 159 160 // GetLayerMountID returns the mount ID for a layer 161 // called from daemon.go Daemon.Shutdown(), and Daemon.Cleanup() (cleanup is actually continerCleanup) 162 // TODO: needs to be refactored to Unmount (see callers), or removed and replaced with GetLayerByID 163 func (i *ImageService) GetLayerMountID(cid string) (string, error) { 164 return i.layerStore.GetMountID(cid) 165 } 166 167 // Cleanup resources before the process is shutdown. 168 // called from daemon.go Daemon.Shutdown() 169 func (i *ImageService) Cleanup() { 170 if err := i.layerStore.Cleanup(); err != nil { 171 logrus.Errorf("Error during layer Store.Cleanup(): %v", err) 172 } 173 } 174 175 // GraphDriverName returns the name of the graph drvier 176 // moved from Daemon.GraphDriverName, used by: 177 // - newContainer 178 // - to report an error in Daemon.Mount(container) 179 func (i *ImageService) GraphDriverName() string { 180 return i.layerStore.DriverName() 181 } 182 183 // ReleaseLayer releases a layer allowing it to be removed 184 // called from delete.go Daemon.cleanupContainer(), and Daemon.containerExport() 185 func (i *ImageService) ReleaseLayer(rwlayer layer.RWLayer, containerOS string) error { 186 metadata, err := i.layerStore.ReleaseRWLayer(rwlayer) 187 layer.LogReleaseMetadata(metadata) 188 if err != nil && !errors.Is(err, layer.ErrMountDoesNotExist) && !errors.Is(err, os.ErrNotExist) { 189 return errors.Wrapf(err, "driver %q failed to remove root filesystem", 190 i.layerStore.DriverName()) 191 } 192 return nil 193 } 194 195 // LayerDiskUsage returns the number of bytes used by layer stores 196 // called from disk_usage.go 197 func (i *ImageService) LayerDiskUsage(ctx context.Context) (int64, error) { 198 var allLayersSize int64 199 layerRefs := i.getLayerRefs() 200 allLayers := i.layerStore.Map() 201 for _, l := range allLayers { 202 select { 203 case <-ctx.Done(): 204 return allLayersSize, ctx.Err() 205 default: 206 size, err := l.DiffSize() 207 if err == nil { 208 if _, ok := layerRefs[l.ChainID()]; ok { 209 allLayersSize += size 210 } 211 } else { 212 logrus.Warnf("failed to get diff size for layer %v", l.ChainID()) 213 } 214 } 215 } 216 return allLayersSize, nil 217 } 218 219 func (i *ImageService) getLayerRefs() map[layer.ChainID]int { 220 tmpImages := i.imageStore.Map() 221 layerRefs := map[layer.ChainID]int{} 222 for id, img := range tmpImages { 223 dgst := digest.Digest(id) 224 if len(i.referenceStore.References(dgst)) == 0 && len(i.imageStore.Children(id)) != 0 { 225 continue 226 } 227 228 rootFS := *img.RootFS 229 rootFS.DiffIDs = nil 230 for _, id := range img.RootFS.DiffIDs { 231 rootFS.Append(id) 232 chid := rootFS.ChainID() 233 layerRefs[chid]++ 234 } 235 } 236 237 return layerRefs 238 } 239 240 // UpdateConfig values 241 // 242 // called from reload.go 243 func (i *ImageService) UpdateConfig(maxDownloads, maxUploads *int) { 244 if i.downloadManager != nil && maxDownloads != nil { 245 i.downloadManager.SetConcurrency(*maxDownloads) 246 } 247 if i.uploadManager != nil && maxUploads != nil { 248 i.uploadManager.SetConcurrency(*maxUploads) 249 } 250 }