image_history.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. package daemon
  2. import (
  3. "fmt"
  4. "time"
  5. "github.com/docker/distribution/reference"
  6. "github.com/docker/docker/api/types/image"
  7. "github.com/docker/docker/layer"
  8. )
  9. // ImageHistory returns a slice of ImageHistory structures for the specified image
  10. // name by walking the image lineage.
  11. func (daemon *Daemon) ImageHistory(name string) ([]*image.HistoryResponseItem, error) {
  12. start := time.Now()
  13. img, err := daemon.GetImage(name)
  14. if err != nil {
  15. return nil, err
  16. }
  17. history := []*image.HistoryResponseItem{}
  18. layerCounter := 0
  19. rootFS := *img.RootFS
  20. rootFS.DiffIDs = nil
  21. for _, h := range img.History {
  22. var layerSize int64
  23. if !h.EmptyLayer {
  24. if len(img.RootFS.DiffIDs) <= layerCounter {
  25. return nil, fmt.Errorf("too many non-empty layers in History section")
  26. }
  27. rootFS.Append(img.RootFS.DiffIDs[layerCounter])
  28. l, err := daemon.layerStore.Get(rootFS.ChainID())
  29. if err != nil {
  30. return nil, err
  31. }
  32. layerSize, err = l.DiffSize()
  33. layer.ReleaseAndLog(daemon.layerStore, l)
  34. if err != nil {
  35. return nil, err
  36. }
  37. layerCounter++
  38. }
  39. history = append([]*image.HistoryResponseItem{{
  40. ID: "<missing>",
  41. Created: h.Created.Unix(),
  42. CreatedBy: h.CreatedBy,
  43. Comment: h.Comment,
  44. Size: layerSize,
  45. }}, history...)
  46. }
  47. // Fill in image IDs and tags
  48. histImg := img
  49. id := img.ID()
  50. for _, h := range history {
  51. h.ID = id.String()
  52. var tags []string
  53. for _, r := range daemon.referenceStore.References(id.Digest()) {
  54. if _, ok := r.(reference.NamedTagged); ok {
  55. tags = append(tags, reference.FamiliarString(r))
  56. }
  57. }
  58. h.Tags = tags
  59. id = histImg.Parent
  60. if id == "" {
  61. break
  62. }
  63. histImg, err = daemon.GetImage(id.String())
  64. if err != nil {
  65. break
  66. }
  67. }
  68. imageActions.WithValues("history").UpdateSince(start)
  69. return history, nil
  70. }