Files
moby/daemon/containerd/imagespec.go
Sebastiaan van Stijn a99b7947e1 daemon: stop propagating Image.DockerVersion field
The DockerVersion field was used by the legacy builder, and set when
importing an image; when importing an image, this would potentially
result in less reproducible images, as the docker version used to import
the image would be encoded in the image's "v1" fields.

For the legacy builder, including the version of docker used to build
the image could still be useful information (but could be set as comment,
similar to what BuildKit does), however, many code paths were also shared
with other parts of the code; e.g., when listing images or inspecting images,
the `DockerVersion` field would always be set to the current version of
the docker daemon, and not taken from the information available in the
image (if any).

This patch removes locations where the `DockerVersion` field was set to
the current version of the daemon binary. When inspecting an image, the
field is still set with the information in the image itself (which may
be empty in most cases).

This also reduces the number of places where the `dockerversion` package
is used, which still needs a new home.

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

120 lines
3.3 KiB
Go

package containerd
import (
"slices"
dockerspec "github.com/moby/docker-image-spec/specs-go/v1"
"github.com/moby/moby/api/types/container"
"github.com/moby/moby/api/types/network"
"github.com/moby/moby/v2/daemon/internal/image"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
// dockerOciImageToDockerImagePartial creates an image.Image from the imagespec.DockerOCIImage
// It doesn't set:
// - V1Image.ContainerConfig
// - V1Image.Container
// - Details
func dockerOciImageToDockerImagePartial(id image.ID, img dockerspec.DockerOCIImage) *image.Image {
v1Image := image.V1Image{
Config: dockerOCIImageConfigToContainerConfig(img.Config),
Architecture: img.Platform.Architecture,
Variant: img.Platform.Variant,
OS: img.Platform.OS,
Author: img.Author,
Created: img.Created,
}
out := image.NewImage(id)
out.V1Image = v1Image
out.RootFS = &image.RootFS{
Type: img.RootFS.Type,
DiffIDs: slices.Clone(img.RootFS.DiffIDs),
}
out.History = img.History
out.OSFeatures = img.OSFeatures
out.OSVersion = img.OSVersion
return out
}
func dockerImageToDockerOCIImage(img image.Image) dockerspec.DockerOCIImage {
return dockerspec.DockerOCIImage{
Image: ocispec.Image{
Created: img.Created,
Author: img.Author,
Platform: ocispec.Platform{
Architecture: img.Architecture,
Variant: img.Variant,
OS: img.OS,
OSVersion: img.OSVersion,
OSFeatures: img.OSFeatures,
},
RootFS: ocispec.RootFS{
Type: img.RootFS.Type,
DiffIDs: slices.Clone(img.RootFS.DiffIDs),
},
History: img.History,
},
Config: containerConfigToDockerOCIImageConfig(img.Config),
}
}
func containerConfigToDockerOCIImageConfig(cfg *container.Config) dockerspec.DockerOCIImageConfig {
var ociCfg ocispec.ImageConfig
var ext dockerspec.DockerOCIImageConfigExt
if cfg != nil {
ociCfg = ocispec.ImageConfig{
User: cfg.User,
Env: cfg.Env,
Entrypoint: cfg.Entrypoint,
Cmd: cfg.Cmd,
Volumes: cfg.Volumes,
WorkingDir: cfg.WorkingDir,
Labels: cfg.Labels,
StopSignal: cfg.StopSignal,
ArgsEscaped: cfg.ArgsEscaped, //nolint:staticcheck // Ignore SA1019. Need to keep it in image.
}
if len(cfg.ExposedPorts) > 0 {
ociCfg.ExposedPorts = map[string]struct{}{}
for k := range cfg.ExposedPorts {
ociCfg.ExposedPorts[k.String()] = struct{}{}
}
}
ext.Healthcheck = cfg.Healthcheck
ext.OnBuild = cfg.OnBuild
ext.Shell = cfg.Shell
}
return dockerspec.DockerOCIImageConfig{
ImageConfig: ociCfg,
DockerOCIImageConfigExt: ext,
}
}
func dockerOCIImageConfigToContainerConfig(cfg dockerspec.DockerOCIImageConfig) *container.Config {
exposedPorts := make(network.PortSet, len(cfg.ExposedPorts))
for k := range cfg.ExposedPorts {
if p, err := network.ParsePort(k); err == nil {
exposedPorts[p] = struct{}{}
}
}
return &container.Config{
Entrypoint: cfg.Entrypoint,
Env: cfg.Env,
Cmd: cfg.Cmd,
User: cfg.User,
WorkingDir: cfg.WorkingDir,
ExposedPorts: exposedPorts,
Volumes: cfg.Volumes,
Labels: cfg.Labels,
ArgsEscaped: cfg.ArgsEscaped, //nolint:staticcheck // Ignore SA1019. Need to keep it in image.
StopSignal: cfg.StopSignal,
Healthcheck: cfg.Healthcheck,
OnBuild: cfg.OnBuild,
Shell: cfg.Shell,
}
}