github.com/uriddle/docker@v0.0.0-20210926094723-4072e6aeb013/daemon/images.go (about) 1 package daemon 2 3 import ( 4 "fmt" 5 "path" 6 "sort" 7 8 "github.com/docker/docker/image" 9 "github.com/docker/docker/layer" 10 "github.com/docker/docker/reference" 11 "github.com/docker/engine-api/types" 12 "github.com/docker/engine-api/types/filters" 13 ) 14 15 var acceptedImageFilterTags = map[string]bool{ 16 "dangling": true, 17 "label": true, 18 } 19 20 // byCreated is a temporary type used to sort a list of images by creation 21 // time. 22 type byCreated []*types.Image 23 24 func (r byCreated) Len() int { return len(r) } 25 func (r byCreated) Swap(i, j int) { r[i], r[j] = r[j], r[i] } 26 func (r byCreated) Less(i, j int) bool { return r[i].Created < r[j].Created } 27 28 // Map returns a map of all images in the ImageStore 29 func (daemon *Daemon) Map() map[image.ID]*image.Image { 30 return daemon.imageStore.Map() 31 } 32 33 // Images returns a filtered list of images. filterArgs is a JSON-encoded set 34 // of filter arguments which will be interpreted by api/types/filters. 35 // filter is a shell glob string applied to repository names. The argument 36 // named all controls whether all images in the graph are filtered, or just 37 // the heads. 38 func (daemon *Daemon) Images(filterArgs, filter string, all bool) ([]*types.Image, error) { 39 var ( 40 allImages map[image.ID]*image.Image 41 err error 42 danglingOnly = false 43 ) 44 45 imageFilters, err := filters.FromParam(filterArgs) 46 if err != nil { 47 return nil, err 48 } 49 if err := imageFilters.Validate(acceptedImageFilterTags); err != nil { 50 return nil, err 51 } 52 53 if imageFilters.Include("dangling") { 54 if imageFilters.ExactMatch("dangling", "true") { 55 danglingOnly = true 56 } else if !imageFilters.ExactMatch("dangling", "false") { 57 return nil, fmt.Errorf("Invalid filter 'dangling=%s'", imageFilters.Get("dangling")) 58 } 59 } 60 if danglingOnly { 61 allImages = daemon.imageStore.Heads() 62 } else { 63 allImages = daemon.imageStore.Map() 64 } 65 66 images := []*types.Image{} 67 68 var filterTagged bool 69 if filter != "" { 70 filterRef, err := reference.ParseNamed(filter) 71 if err == nil { // parse error means wildcard repo 72 if _, ok := filterRef.(reference.NamedTagged); ok { 73 filterTagged = true 74 } 75 } 76 } 77 78 for id, img := range allImages { 79 if imageFilters.Include("label") { 80 // Very old image that do not have image.Config (or even labels) 81 if img.Config == nil { 82 continue 83 } 84 // We are now sure image.Config is not nil 85 if !imageFilters.MatchKVList("label", img.Config.Labels) { 86 continue 87 } 88 } 89 90 layerID := img.RootFS.ChainID() 91 var size int64 92 if layerID != "" { 93 l, err := daemon.layerStore.Get(layerID) 94 if err != nil { 95 return nil, err 96 } 97 98 size, err = l.Size() 99 layer.ReleaseAndLog(daemon.layerStore, l) 100 if err != nil { 101 return nil, err 102 } 103 } 104 105 newImage := newImage(img, size) 106 107 for _, ref := range daemon.referenceStore.References(id) { 108 if filter != "" { // filter by tag/repo name 109 if filterTagged { // filter by tag, require full ref match 110 if ref.String() != filter { 111 continue 112 } 113 } else if matched, err := path.Match(filter, ref.Name()); !matched || err != nil { // name only match, FIXME: docs say exact 114 continue 115 } 116 } 117 if _, ok := ref.(reference.Canonical); ok { 118 newImage.RepoDigests = append(newImage.RepoDigests, ref.String()) 119 } 120 if _, ok := ref.(reference.NamedTagged); ok { 121 newImage.RepoTags = append(newImage.RepoTags, ref.String()) 122 } 123 } 124 if newImage.RepoDigests == nil && newImage.RepoTags == nil { 125 if all || len(daemon.imageStore.Children(id)) == 0 { 126 127 if imageFilters.Include("dangling") && !danglingOnly { 128 //dangling=false case, so dangling image is not needed 129 continue 130 } 131 if filter != "" { // skip images with no references if filtering by tag 132 continue 133 } 134 newImage.RepoDigests = []string{"<none>@<none>"} 135 newImage.RepoTags = []string{"<none>:<none>"} 136 } else { 137 continue 138 } 139 } else if danglingOnly { 140 continue 141 } 142 143 images = append(images, newImage) 144 } 145 146 sort.Sort(sort.Reverse(byCreated(images))) 147 148 return images, nil 149 } 150 151 func newImage(image *image.Image, size int64) *types.Image { 152 newImage := new(types.Image) 153 newImage.ParentID = image.Parent.String() 154 newImage.ID = image.ID().String() 155 newImage.Created = image.Created.Unix() 156 newImage.Size = size 157 newImage.VirtualSize = size 158 if image.Config != nil { 159 newImage.Labels = image.Config.Labels 160 } 161 return newImage 162 }