github.com/afbjorklund/moby@v20.10.5+incompatible/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  }