github.com/LazyboyChen7/engine@v17.12.1-ce-rc2+incompatible/image/image.go (about) 1 package image 2 3 import ( 4 "encoding/json" 5 "errors" 6 "io" 7 "runtime" 8 "strings" 9 "time" 10 11 "github.com/docker/docker/api/types/container" 12 "github.com/docker/docker/dockerversion" 13 "github.com/docker/docker/layer" 14 "github.com/opencontainers/go-digest" 15 ) 16 17 // ID is the content-addressable ID of an image. 18 type ID digest.Digest 19 20 func (id ID) String() string { 21 return id.Digest().String() 22 } 23 24 // Digest converts ID into a digest 25 func (id ID) Digest() digest.Digest { 26 return digest.Digest(id) 27 } 28 29 // IDFromDigest creates an ID from a digest 30 func IDFromDigest(digest digest.Digest) ID { 31 return ID(digest) 32 } 33 34 // V1Image stores the V1 image configuration. 35 type V1Image struct { 36 // ID is a unique 64 character identifier of the image 37 ID string `json:"id,omitempty"` 38 // Parent is the ID of the parent image 39 Parent string `json:"parent,omitempty"` 40 // Comment is the commit message that was set when committing the image 41 Comment string `json:"comment,omitempty"` 42 // Created is the timestamp at which the image was created 43 Created time.Time `json:"created"` 44 // Container is the id of the container used to commit 45 Container string `json:"container,omitempty"` 46 // ContainerConfig is the configuration of the container that is committed into the image 47 ContainerConfig container.Config `json:"container_config,omitempty"` 48 // DockerVersion specifies the version of Docker that was used to build the image 49 DockerVersion string `json:"docker_version,omitempty"` 50 // Author is the name of the author that was specified when committing the image 51 Author string `json:"author,omitempty"` 52 // Config is the configuration of the container received from the client 53 Config *container.Config `json:"config,omitempty"` 54 // Architecture is the hardware that the image is built and runs on 55 Architecture string `json:"architecture,omitempty"` 56 // OS is the operating system used to build and run the image 57 OS string `json:"os,omitempty"` 58 // Size is the total size of the image including all layers it is composed of 59 Size int64 `json:",omitempty"` 60 } 61 62 // Image stores the image configuration 63 type Image struct { 64 V1Image 65 Parent ID `json:"parent,omitempty"` 66 RootFS *RootFS `json:"rootfs,omitempty"` 67 History []History `json:"history,omitempty"` 68 OSVersion string `json:"os.version,omitempty"` 69 OSFeatures []string `json:"os.features,omitempty"` 70 71 // rawJSON caches the immutable JSON associated with this image. 72 rawJSON []byte 73 74 // computedID is the ID computed from the hash of the image config. 75 // Not to be confused with the legacy V1 ID in V1Image. 76 computedID ID 77 } 78 79 // RawJSON returns the immutable JSON associated with the image. 80 func (img *Image) RawJSON() []byte { 81 return img.rawJSON 82 } 83 84 // ID returns the image's content-addressable ID. 85 func (img *Image) ID() ID { 86 return img.computedID 87 } 88 89 // ImageID stringifies ID. 90 func (img *Image) ImageID() string { 91 return img.ID().String() 92 } 93 94 // RunConfig returns the image's container config. 95 func (img *Image) RunConfig() *container.Config { 96 return img.Config 97 } 98 99 // OperatingSystem returns the image's operating system. If not populated, defaults to the host runtime OS. 100 func (img *Image) OperatingSystem() string { 101 os := img.OS 102 if os == "" { 103 os = runtime.GOOS 104 } 105 return os 106 } 107 108 // MarshalJSON serializes the image to JSON. It sorts the top-level keys so 109 // that JSON that's been manipulated by a push/pull cycle with a legacy 110 // registry won't end up with a different key order. 111 func (img *Image) MarshalJSON() ([]byte, error) { 112 type MarshalImage Image 113 114 pass1, err := json.Marshal(MarshalImage(*img)) 115 if err != nil { 116 return nil, err 117 } 118 119 var c map[string]*json.RawMessage 120 if err := json.Unmarshal(pass1, &c); err != nil { 121 return nil, err 122 } 123 return json.Marshal(c) 124 } 125 126 // ChildConfig is the configuration to apply to an Image to create a new 127 // Child image. Other properties of the image are copied from the parent. 128 type ChildConfig struct { 129 ContainerID string 130 Author string 131 Comment string 132 DiffID layer.DiffID 133 ContainerConfig *container.Config 134 Config *container.Config 135 } 136 137 // NewChildImage creates a new Image as a child of this image. 138 func NewChildImage(img *Image, child ChildConfig, platform string) *Image { 139 isEmptyLayer := layer.IsEmpty(child.DiffID) 140 var rootFS *RootFS 141 if img.RootFS != nil { 142 rootFS = img.RootFS.Clone() 143 } else { 144 rootFS = NewRootFS() 145 } 146 147 if !isEmptyLayer { 148 rootFS.Append(child.DiffID) 149 } 150 imgHistory := NewHistory( 151 child.Author, 152 child.Comment, 153 strings.Join(child.ContainerConfig.Cmd, " "), 154 isEmptyLayer) 155 156 return &Image{ 157 V1Image: V1Image{ 158 DockerVersion: dockerversion.Version, 159 Config: child.Config, 160 Architecture: runtime.GOARCH, 161 OS: platform, 162 Container: child.ContainerID, 163 ContainerConfig: *child.ContainerConfig, 164 Author: child.Author, 165 Created: imgHistory.Created, 166 }, 167 RootFS: rootFS, 168 History: append(img.History, imgHistory), 169 OSFeatures: img.OSFeatures, 170 OSVersion: img.OSVersion, 171 } 172 } 173 174 // History stores build commands that were used to create an image 175 type History struct { 176 // Created is the timestamp at which the image was created 177 Created time.Time `json:"created"` 178 // Author is the name of the author that was specified when committing the image 179 Author string `json:"author,omitempty"` 180 // CreatedBy keeps the Dockerfile command used while building the image 181 CreatedBy string `json:"created_by,omitempty"` 182 // Comment is the commit message that was set when committing the image 183 Comment string `json:"comment,omitempty"` 184 // EmptyLayer is set to true if this history item did not generate a 185 // layer. Otherwise, the history item is associated with the next 186 // layer in the RootFS section. 187 EmptyLayer bool `json:"empty_layer,omitempty"` 188 } 189 190 // NewHistory creates a new history struct from arguments, and sets the created 191 // time to the current time in UTC 192 func NewHistory(author, comment, createdBy string, isEmptyLayer bool) History { 193 return History{ 194 Author: author, 195 Created: time.Now().UTC(), 196 CreatedBy: createdBy, 197 Comment: comment, 198 EmptyLayer: isEmptyLayer, 199 } 200 } 201 202 // Exporter provides interface for loading and saving images 203 type Exporter interface { 204 Load(io.ReadCloser, io.Writer, bool) error 205 // TODO: Load(net.Context, io.ReadCloser, <- chan StatusMessage) error 206 Save([]string, io.Writer) error 207 } 208 209 // NewFromJSON creates an Image configuration from json. 210 func NewFromJSON(src []byte) (*Image, error) { 211 img := &Image{} 212 213 if err := json.Unmarshal(src, img); err != nil { 214 return nil, err 215 } 216 if img.RootFS == nil { 217 return nil, errors.New("invalid image JSON, no RootFS key") 218 } 219 220 img.rawJSON = src 221 222 return img, nil 223 }