github.com/toplink-cn/moby@v0.0.0-20240305205811-460b4aebdf81/image/image.go (about) 1 package image // import "github.com/docker/docker/image" 2 3 import ( 4 "encoding/json" 5 "errors" 6 "io" 7 "runtime" 8 "strings" 9 "time" 10 11 "github.com/distribution/reference" 12 "github.com/docker/docker/api/types/container" 13 "github.com/docker/docker/dockerversion" 14 "github.com/docker/docker/layer" 15 "github.com/opencontainers/go-digest" 16 ocispec "github.com/opencontainers/image-spec/specs-go/v1" 17 ) 18 19 // ID is the content-addressable ID of an image. 20 type ID digest.Digest 21 22 func (id ID) String() string { 23 return id.Digest().String() 24 } 25 26 // Digest converts ID into a digest 27 func (id ID) Digest() digest.Digest { 28 return digest.Digest(id) 29 } 30 31 // V1Image stores the V1 image configuration. 32 type V1Image struct { 33 // ID is a unique 64 character identifier of the image 34 ID string `json:"id,omitempty"` 35 36 // Parent is the ID of the parent image. 37 // 38 // Depending on how the image was created, this field may be empty and 39 // is only set for images that were built/created locally. This field 40 // is empty if the image was pulled from an image registry. 41 Parent string `json:"parent,omitempty"` 42 43 // Comment is an optional message that can be set when committing or 44 // importing the image. 45 Comment string `json:"comment,omitempty"` 46 47 // Created is the timestamp at which the image was created 48 Created *time.Time `json:"created"` 49 50 // Container is the ID of the container that was used to create the image. 51 // 52 // Depending on how the image was created, this field may be empty. 53 Container string `json:"container,omitempty"` 54 55 // ContainerConfig is the configuration of the container that was committed 56 // into the image. 57 ContainerConfig container.Config `json:"container_config,omitempty"` 58 59 // DockerVersion is the version of Docker that was used to build the image. 60 // 61 // Depending on how the image was created, this field may be empty. 62 DockerVersion string `json:"docker_version,omitempty"` 63 64 // Author is the name of the author that was specified when committing the 65 // image, or as specified through MAINTAINER (deprecated) in the Dockerfile. 66 Author string `json:"author,omitempty"` 67 68 // Config is the configuration of the container received from the client. 69 Config *container.Config `json:"config,omitempty"` 70 71 // Architecture is the hardware CPU architecture that the image runs on. 72 Architecture string `json:"architecture,omitempty"` 73 74 // Variant is the CPU architecture variant (presently ARM-only). 75 Variant string `json:"variant,omitempty"` 76 77 // OS is the Operating System the image is built to run on. 78 OS string `json:"os,omitempty"` 79 80 // Size is the total size of the image including all layers it is composed of. 81 Size int64 `json:",omitempty"` 82 } 83 84 // Image stores the image configuration 85 type Image struct { 86 V1Image 87 88 // Parent is the ID of the parent image. 89 // 90 // Depending on how the image was created, this field may be empty and 91 // is only set for images that were built/created locally. This field 92 // is empty if the image was pulled from an image registry. 93 Parent ID `json:"parent,omitempty"` //nolint:govet 94 95 // RootFS contains information about the image's RootFS, including the 96 // layer IDs. 97 RootFS *RootFS `json:"rootfs,omitempty"` 98 History []History `json:"history,omitempty"` 99 100 // OsVersion is the version of the Operating System the image is built to 101 // run on (especially for Windows). 102 OSVersion string `json:"os.version,omitempty"` 103 OSFeatures []string `json:"os.features,omitempty"` 104 105 // rawJSON caches the immutable JSON associated with this image. 106 rawJSON []byte 107 108 // computedID is the ID computed from the hash of the image config. 109 // Not to be confused with the legacy V1 ID in V1Image. 110 computedID ID 111 112 // Details holds additional details about image 113 Details *Details `json:"-"` 114 } 115 116 // Details provides additional image data 117 type Details struct { 118 References []reference.Named 119 Size int64 120 Metadata map[string]string 121 Driver string 122 LastUpdated time.Time 123 } 124 125 // RawJSON returns the immutable JSON associated with the image. 126 func (img *Image) RawJSON() []byte { 127 return img.rawJSON 128 } 129 130 // ID returns the image's content-addressable ID. 131 func (img *Image) ID() ID { 132 return img.computedID 133 } 134 135 // ImageID stringifies ID. 136 func (img *Image) ImageID() string { 137 return img.ID().String() 138 } 139 140 // RunConfig returns the image's container config. 141 func (img *Image) RunConfig() *container.Config { 142 return img.Config 143 } 144 145 // BaseImgArch returns the image's architecture. If not populated, defaults to the host runtime arch. 146 func (img *Image) BaseImgArch() string { 147 arch := img.Architecture 148 if arch == "" { 149 arch = runtime.GOARCH 150 } 151 return arch 152 } 153 154 // BaseImgVariant returns the image's variant, whether populated or not. 155 // This avoids creating an inconsistency where the stored image variant 156 // is "greater than" (i.e. v8 vs v6) the actual image variant. 157 func (img *Image) BaseImgVariant() string { 158 return img.Variant 159 } 160 161 // OperatingSystem returns the image's operating system. If not populated, defaults to the host runtime OS. 162 func (img *Image) OperatingSystem() string { 163 os := img.OS 164 if os == "" { 165 os = runtime.GOOS 166 } 167 return os 168 } 169 170 // Platform generates an OCI platform from the image 171 func (img *Image) Platform() ocispec.Platform { 172 return ocispec.Platform{ 173 Architecture: img.Architecture, 174 OS: img.OS, 175 OSVersion: img.OSVersion, 176 OSFeatures: img.OSFeatures, 177 Variant: img.Variant, 178 } 179 } 180 181 // MarshalJSON serializes the image to JSON. It sorts the top-level keys so 182 // that JSON that's been manipulated by a push/pull cycle with a legacy 183 // registry won't end up with a different key order. 184 func (img *Image) MarshalJSON() ([]byte, error) { 185 type MarshalImage Image 186 187 pass1, err := json.Marshal(MarshalImage(*img)) 188 if err != nil { 189 return nil, err 190 } 191 192 var c map[string]*json.RawMessage 193 if err := json.Unmarshal(pass1, &c); err != nil { 194 return nil, err 195 } 196 return json.Marshal(c) 197 } 198 199 // ChildConfig is the configuration to apply to an Image to create a new 200 // Child image. Other properties of the image are copied from the parent. 201 type ChildConfig struct { 202 ContainerID string 203 Author string 204 Comment string 205 DiffID layer.DiffID 206 ContainerConfig *container.Config 207 Config *container.Config 208 } 209 210 // NewImage creates a new image with the given ID 211 func NewImage(id ID) *Image { 212 return &Image{ 213 computedID: id, 214 } 215 } 216 217 // NewChildImage creates a new Image as a child of this image. 218 func NewChildImage(img *Image, child ChildConfig, os string) *Image { 219 isEmptyLayer := layer.IsEmpty(child.DiffID) 220 var rootFS *RootFS 221 if img.RootFS != nil { 222 rootFS = img.RootFS.Clone() 223 } else { 224 rootFS = NewRootFS() 225 } 226 227 if !isEmptyLayer { 228 rootFS.Append(child.DiffID) 229 } 230 imgHistory := NewHistory( 231 child.Author, 232 child.Comment, 233 strings.Join(child.ContainerConfig.Cmd, " "), 234 isEmptyLayer) 235 236 return &Image{ 237 V1Image: V1Image{ 238 DockerVersion: dockerversion.Version, 239 Config: child.Config, 240 Architecture: img.BaseImgArch(), 241 Variant: img.BaseImgVariant(), 242 OS: os, 243 Container: child.ContainerID, 244 ContainerConfig: *child.ContainerConfig, 245 Author: child.Author, 246 Created: imgHistory.Created, 247 }, 248 RootFS: rootFS, 249 History: append(img.History, imgHistory), 250 OSFeatures: img.OSFeatures, 251 OSVersion: img.OSVersion, 252 } 253 } 254 255 // Clone clones an image and changes ID. 256 func Clone(base *Image, id ID) *Image { 257 img := *base 258 img.RootFS = img.RootFS.Clone() 259 img.V1Image.ID = id.String() 260 img.computedID = id 261 return &img 262 } 263 264 // History stores build commands that were used to create an image 265 type History = ocispec.History 266 267 // NewHistory creates a new history struct from arguments, and sets the created 268 // time to the current time in UTC 269 func NewHistory(author, comment, createdBy string, isEmptyLayer bool) History { 270 now := time.Now().UTC() 271 return History{ 272 Author: author, 273 Created: &now, 274 CreatedBy: createdBy, 275 Comment: comment, 276 EmptyLayer: isEmptyLayer, 277 } 278 } 279 280 // Exporter provides interface for loading and saving images 281 type Exporter interface { 282 Load(io.ReadCloser, io.Writer, bool) error 283 // TODO: Load(net.Context, io.ReadCloser, <- chan StatusMessage) error 284 Save([]string, io.Writer) error 285 } 286 287 // NewFromJSON creates an Image configuration from json. 288 func NewFromJSON(src []byte) (*Image, error) { 289 img := &Image{} 290 291 if err := json.Unmarshal(src, img); err != nil { 292 return nil, err 293 } 294 if img.RootFS == nil { 295 return nil, errors.New("invalid image JSON, no RootFS key") 296 } 297 298 img.rawJSON = src 299 300 return img, nil 301 }