image_changes.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. package containerd
  2. import (
  3. "context"
  4. "encoding/json"
  5. "github.com/containerd/containerd/content"
  6. "github.com/containerd/containerd/mount"
  7. "github.com/docker/docker/container"
  8. "github.com/docker/docker/pkg/archive"
  9. "github.com/google/uuid"
  10. "github.com/opencontainers/image-spec/identity"
  11. ocispec "github.com/opencontainers/image-spec/specs-go/v1"
  12. "github.com/sirupsen/logrus"
  13. )
  14. func (i *ImageService) Changes(ctx context.Context, container *container.Container) ([]archive.Change, error) {
  15. cs := i.client.ContentStore()
  16. imageManifestBytes, err := content.ReadBlob(ctx, cs, *container.ImageManifest)
  17. if err != nil {
  18. return nil, err
  19. }
  20. var manifest ocispec.Manifest
  21. if err := json.Unmarshal(imageManifestBytes, &manifest); err != nil {
  22. return nil, err
  23. }
  24. imageConfigBytes, err := content.ReadBlob(ctx, cs, manifest.Config)
  25. if err != nil {
  26. return nil, err
  27. }
  28. var image ocispec.Image
  29. if err := json.Unmarshal(imageConfigBytes, &image); err != nil {
  30. return nil, err
  31. }
  32. rnd, err := uuid.NewRandom()
  33. if err != nil {
  34. return nil, err
  35. }
  36. snapshotter := i.client.SnapshotService(i.snapshotter)
  37. diffIDs := image.RootFS.DiffIDs
  38. parent, err := snapshotter.View(ctx, rnd.String(), identity.ChainID(diffIDs).String())
  39. if err != nil {
  40. return nil, err
  41. }
  42. defer func() {
  43. if err := snapshotter.Remove(ctx, rnd.String()); err != nil {
  44. logrus.WithError(err).WithField("key", rnd.String()).Warn("remove temporary snapshot")
  45. }
  46. }()
  47. mounts, err := snapshotter.Mounts(ctx, container.ID)
  48. if err != nil {
  49. return nil, err
  50. }
  51. var changes []archive.Change
  52. err = mount.WithReadonlyTempMount(ctx, mounts, func(fs string) error {
  53. return mount.WithTempMount(ctx, parent, func(root string) error {
  54. changes, err = archive.ChangesDirs(fs, root)
  55. return err
  56. })
  57. })
  58. return changes, err
  59. }