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