moby/daemon/images/image_import.go
Sebastiaan van Stijn a3c97beee0
image: implement CheckOS, deprecate pkg/system IsOSSupported
Implement a function that returns an error to replace existing uses of
the IsOSSupported utility, where callers had to produce the error after
checking.

The IsOSSupported function was used in combination with images, so implementing
a utility in "image" to prevent having to import pkg/system (which contains many
unrelated functions)

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-09-07 22:14:44 +02:00

90 lines
2.5 KiB
Go

package images // import "github.com/docker/docker/daemon/images"
import (
"context"
"encoding/json"
"io"
"time"
"github.com/containerd/containerd/platforms"
"github.com/distribution/reference"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/events"
"github.com/docker/docker/builder/dockerfile"
"github.com/docker/docker/dockerversion"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/image"
"github.com/docker/docker/layer"
"github.com/docker/docker/pkg/archive"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
// ImportImage imports an image, getting the archived layer data from layerReader.
// Uncompressed layer archive is passed to the layerStore and handled by the
// underlying graph driver.
// Image is tagged with the given reference.
// If the platform is nil, the default host platform is used.
// Message is used as the image's history comment.
// Image configuration is derived from the dockerfile instructions in changes.
func (i *ImageService) ImportImage(ctx context.Context, newRef reference.Named, platform *ocispec.Platform, msg string, layerReader io.Reader, changes []string) (image.ID, error) {
if platform == nil {
def := platforms.DefaultSpec()
platform = &def
}
if err := image.CheckOS(platform.OS); err != nil {
return "", err
}
config, err := dockerfile.BuildFromConfig(ctx, &container.Config{}, changes, platform.OS)
if err != nil {
return "", errdefs.InvalidParameter(err)
}
inflatedLayerData, err := archive.DecompressStream(layerReader)
if err != nil {
return "", err
}
l, err := i.layerStore.Register(inflatedLayerData, "")
if err != nil {
return "", err
}
defer layer.ReleaseAndLog(i.layerStore, l)
created := time.Now().UTC()
imgConfig, err := json.Marshal(&image.Image{
V1Image: image.V1Image{
DockerVersion: dockerversion.Version,
Config: config,
Architecture: platform.Architecture,
Variant: platform.Variant,
OS: platform.OS,
Created: &created,
Comment: msg,
},
RootFS: &image.RootFS{
Type: "layers",
DiffIDs: []layer.DiffID{l.DiffID()},
},
History: []image.History{{
Created: &created,
Comment: msg,
}},
})
if err != nil {
return "", err
}
id, err := i.imageStore.Create(imgConfig)
if err != nil {
return "", err
}
if newRef != nil {
if err := i.TagImage(ctx, id, newRef); err != nil {
return "", err
}
}
i.LogImageEvent(id.String(), id.String(), events.ActionImport)
return id, nil
}