image_history.go 1.9 KB

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