service.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. package containerd
  2. import (
  3. "context"
  4. "fmt"
  5. "sync/atomic"
  6. "github.com/containerd/containerd"
  7. cerrdefs "github.com/containerd/containerd/errdefs"
  8. "github.com/containerd/containerd/log"
  9. "github.com/containerd/containerd/plugin"
  10. "github.com/containerd/containerd/remotes/docker"
  11. "github.com/containerd/containerd/snapshots"
  12. "github.com/docker/distribution/reference"
  13. "github.com/docker/docker/container"
  14. daemonevents "github.com/docker/docker/daemon/events"
  15. "github.com/docker/docker/daemon/images"
  16. "github.com/docker/docker/daemon/snapshotter"
  17. "github.com/docker/docker/errdefs"
  18. "github.com/docker/docker/image"
  19. "github.com/docker/docker/layer"
  20. "github.com/docker/docker/registry"
  21. ocispec "github.com/opencontainers/image-spec/specs-go/v1"
  22. "github.com/pkg/errors"
  23. "github.com/sirupsen/logrus"
  24. )
  25. // ImageService implements daemon.ImageService
  26. type ImageService struct {
  27. client *containerd.Client
  28. containers container.Store
  29. snapshotter string
  30. registryHosts docker.RegistryHosts
  31. registryService RegistryConfigProvider
  32. eventsService *daemonevents.Events
  33. pruneRunning atomic.Bool
  34. refCountMounter snapshotter.Mounter
  35. }
  36. type RegistryConfigProvider interface {
  37. IsInsecureRegistry(host string) bool
  38. ResolveRepository(name reference.Named) (*registry.RepositoryInfo, error)
  39. }
  40. type ImageServiceConfig struct {
  41. Client *containerd.Client
  42. Containers container.Store
  43. Snapshotter string
  44. RegistryHosts docker.RegistryHosts
  45. Registry RegistryConfigProvider
  46. EventsService *daemonevents.Events
  47. RefCountMounter snapshotter.Mounter
  48. }
  49. // NewService creates a new ImageService.
  50. func NewService(config ImageServiceConfig) *ImageService {
  51. return &ImageService{
  52. client: config.Client,
  53. containers: config.Containers,
  54. snapshotter: config.Snapshotter,
  55. registryHosts: config.RegistryHosts,
  56. registryService: config.Registry,
  57. eventsService: config.EventsService,
  58. refCountMounter: config.RefCountMounter,
  59. }
  60. }
  61. // DistributionServices return services controlling daemon image storage.
  62. func (i *ImageService) DistributionServices() images.DistributionServices {
  63. return images.DistributionServices{}
  64. }
  65. // CountImages returns the number of images stored by ImageService
  66. // called from info.go
  67. func (i *ImageService) CountImages() int {
  68. imgs, err := i.client.ListImages(context.TODO())
  69. if err != nil {
  70. return 0
  71. }
  72. return len(imgs)
  73. }
  74. // CreateLayer creates a filesystem layer for a container.
  75. // called from create.go
  76. // TODO: accept an opt struct instead of container?
  77. func (i *ImageService) CreateLayer(container *container.Container, initFunc layer.MountInit) (layer.RWLayer, error) {
  78. return nil, errdefs.NotImplemented(errdefs.NotImplemented(errors.New("not implemented")))
  79. }
  80. // LayerStoreStatus returns the status for each layer store
  81. // called from info.go
  82. func (i *ImageService) LayerStoreStatus() [][2]string {
  83. // TODO(thaJeztah) do we want to add more details about the driver here?
  84. return [][2]string{
  85. {"driver-type", string(plugin.SnapshotPlugin)},
  86. }
  87. }
  88. // GetLayerMountID returns the mount ID for a layer
  89. // called from daemon.go Daemon.Shutdown(), and Daemon.Cleanup() (cleanup is actually continerCleanup)
  90. // TODO: needs to be refactored to Unmount (see callers), or removed and replaced with GetLayerByID
  91. func (i *ImageService) GetLayerMountID(cid string) (string, error) {
  92. return "", errdefs.NotImplemented(errors.New("not implemented"))
  93. }
  94. // Cleanup resources before the process is shutdown.
  95. // called from daemon.go Daemon.Shutdown()
  96. func (i *ImageService) Cleanup() error {
  97. return nil
  98. }
  99. // StorageDriver returns the name of the default storage-driver (snapshotter)
  100. // used by the ImageService.
  101. func (i *ImageService) StorageDriver() string {
  102. return i.snapshotter
  103. }
  104. // ReleaseLayer releases a layer allowing it to be removed
  105. // called from delete.go Daemon.cleanupContainer(), and Daemon.containerExport()
  106. func (i *ImageService) ReleaseLayer(rwlayer layer.RWLayer) error {
  107. return errdefs.NotImplemented(errors.New("not implemented"))
  108. }
  109. // LayerDiskUsage returns the number of bytes used by layer stores
  110. // called from disk_usage.go
  111. func (i *ImageService) LayerDiskUsage(ctx context.Context) (int64, error) {
  112. var allLayersSize int64
  113. // TODO(thaJeztah): do we need to take multiple snapshotters into account? See https://github.com/moby/moby/issues/45273
  114. snapshotter := i.client.SnapshotService(i.snapshotter)
  115. snapshotter.Walk(ctx, func(ctx context.Context, info snapshots.Info) error {
  116. usage, err := snapshotter.Usage(ctx, info.Name)
  117. if err != nil {
  118. return err
  119. }
  120. allLayersSize += usage.Size
  121. return nil
  122. })
  123. return allLayersSize, nil
  124. }
  125. // UpdateConfig values
  126. //
  127. // called from reload.go
  128. func (i *ImageService) UpdateConfig(maxDownloads, maxUploads int) {
  129. panic("not implemented")
  130. }
  131. // GetLayerFolders returns the layer folders from an image RootFS.
  132. func (i *ImageService) GetLayerFolders(img *image.Image, rwLayer layer.RWLayer) ([]string, error) {
  133. return nil, errdefs.NotImplemented(errors.New("not implemented"))
  134. }
  135. // GetContainerLayerSize returns the real size & virtual size of the container.
  136. func (i *ImageService) GetContainerLayerSize(ctx context.Context, containerID string) (int64, int64, error) {
  137. ctr := i.containers.Get(containerID)
  138. if ctr == nil {
  139. return 0, 0, nil
  140. }
  141. snapshotter := i.client.SnapshotService(ctr.Driver)
  142. rwLayerUsage, err := snapshotter.Usage(ctx, containerID)
  143. if err != nil {
  144. if cerrdefs.IsNotFound(err) {
  145. return 0, 0, errdefs.NotFound(fmt.Errorf("rw layer snapshot not found for container %s", containerID))
  146. }
  147. return 0, 0, errdefs.System(errors.Wrapf(err, "snapshotter.Usage failed for %s", containerID))
  148. }
  149. unpackedUsage, err := calculateSnapshotParentUsage(ctx, snapshotter, containerID)
  150. if err != nil {
  151. if cerrdefs.IsNotFound(err) {
  152. log.G(ctx).WithField("ctr", containerID).Warn("parent of container snapshot no longer present")
  153. } else {
  154. log.G(ctx).WithError(err).WithField("ctr", containerID).Warn("unexpected error when calculating usage of the parent snapshots")
  155. }
  156. }
  157. log.G(ctx).WithFields(logrus.Fields{
  158. "rwLayerUsage": rwLayerUsage.Size,
  159. "unpacked": unpackedUsage.Size,
  160. }).Debug("GetContainerLayerSize")
  161. // TODO(thaJeztah): include content-store size for the image (similar to "GET /images/json")
  162. return rwLayerUsage.Size, rwLayerUsage.Size + unpackedUsage.Size, nil
  163. }
  164. // getContainerImageManifest safely dereferences ImageManifest.
  165. // ImageManifest can be nil for containers created with Docker Desktop with old
  166. // containerd image store integration enabled which didn't set this field.
  167. func getContainerImageManifest(ctr *container.Container) (ocispec.Descriptor, error) {
  168. if ctr.ImageManifest == nil {
  169. return ocispec.Descriptor{}, errdefs.InvalidParameter(errors.New("container is missing ImageManifest (probably created on old version), please recreate it"))
  170. }
  171. return *ctr.ImageManifest, nil
  172. }