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