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, } }