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  }