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