Files
moby/daemon/images/image_inspect.go
Sebastiaan van Stijn f8d3c4e4a7 api/types/image: InspectResponse: remove deprecated Parent, DockerVersion
The InspectResponse type contains various fields that are deprecated
and removed from current API versions, but that were kept for the API
server to produce the fields when downgrading to older API versions.

- The `Parent` field is only used for the legacy builder, and only set for
  images that are built locally (i.e., not persisted when pulling an image).
- The `DockerVersion` field is only set when building images with the legacy
  builder, and empty in most cases.

Both fields were implicitly deprecated with the deprecation of the legacy
builder, and deprecated for the API in [moby@bd8a99b], which was backported
to the 28.x release.

This patch:

- Removes the deprecated fields from the `InspectResposne` struct; this
  means that [`client.ImageInspect`] won't unmarshal those fields, but
  the [`docker image inspect`] CLI command defaults to printing the raw
  output as returned by the API, so can continue to show any field returned
  in the API response. As a side-note; we should change the CLI to default
  to show the unmarshalled response, and introduce a `--format=jsonraw`
  (or `--raw`) option to make printing the raw response opt-in.
- Updates the API server to backfill the fields if they are set.

[moby@bd8a99b]: bd8a99b400
[`client.ImageInspect`]: f739c61c69/client/image_inspect.go (L14-L64)
[`docker image inspect`]: 74e3520724/cli/command/image/inspect.go (L59-L81)

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-10-07 13:31:17 +02:00

108 lines
3.1 KiB
Go

package images
import (
"context"
"time"
"github.com/distribution/reference"
imagetypes "github.com/moby/moby/api/types/image"
"github.com/moby/moby/api/types/storage"
"github.com/moby/moby/v2/daemon/internal/image"
"github.com/moby/moby/v2/daemon/internal/layer"
"github.com/moby/moby/v2/daemon/server/imagebackend"
)
func (i *ImageService) ImageInspect(ctx context.Context, refOrID string, opts imagebackend.ImageInspectOpts) (*imagebackend.InspectData, error) {
img, err := i.GetImage(ctx, refOrID, imagebackend.GetImageOpts{Platform: opts.Platform})
if err != nil {
return nil, err
}
size, layerMetadata, err := i.getLayerSizeAndMetadata(img)
if err != nil {
return nil, err
}
lastUpdated, err := i.imageStore.GetLastUpdated(img.ID())
if err != nil {
return nil, err
}
var repoTags, repoDigests []string
for _, ref := range i.referenceStore.References(img.ID().Digest()) {
switch ref.(type) {
case reference.NamedTagged:
repoTags = append(repoTags, reference.FamiliarString(ref))
case reference.Canonical:
repoDigests = append(repoDigests, reference.FamiliarString(ref))
}
}
comment := img.Comment
if comment == "" && len(img.History) > 0 {
comment = img.History[len(img.History)-1].Comment
}
var created string
if img.Created != nil {
created = img.Created.Format(time.RFC3339Nano)
}
var layers []string
for _, l := range img.RootFS.DiffIDs {
layers = append(layers, l.String())
}
imgConfig := containerConfigToDockerOCIImageConfig(img.Config)
return &imagebackend.InspectData{
InspectResponse: imagetypes.InspectResponse{
ID: img.ID().String(),
RepoTags: repoTags,
RepoDigests: repoDigests,
Comment: comment,
Created: created,
Author: img.Author,
Config: &imgConfig,
Architecture: img.Architecture,
Variant: img.Variant,
Os: img.OperatingSystem(),
OsVersion: img.OSVersion,
Size: size,
GraphDriver: &storage.DriverData{
Name: i.layerStore.DriverName(),
Data: layerMetadata,
},
RootFS: imagetypes.RootFS{
Type: img.RootFS.Type,
Layers: layers,
},
Metadata: imagetypes.Metadata{
LastTagTime: lastUpdated,
},
},
Parent: img.Parent.String(), // field is deprecated with the legacy builder, but still included in response when present (built with legacy builder).
DockerVersion: img.DockerVersion, // field is deprecated with the legacy builder, but still included in response when present.
Container: img.Container, // field is deprecated, but still set on API < v1.45.
ContainerConfig: &img.ContainerConfig, // field is deprecated, but still set on API < v1.45.
}, nil
}
func (i *ImageService) getLayerSizeAndMetadata(img *image.Image) (int64, map[string]string, error) {
var size int64
var layerMetadata map[string]string
layerID := img.RootFS.ChainID()
if layerID != "" {
l, err := i.layerStore.Get(layerID)
if err != nil {
return 0, nil, err
}
defer layer.ReleaseAndLog(i.layerStore, l)
size = l.Size()
layerMetadata, err = l.Metadata()
if err != nil {
return 0, nil, err
}
}
return size, layerMetadata, nil
}