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  }