github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/daemon/images/image_import.go (about) 1 package images // import "github.com/docker/docker/daemon/images" 2 3 import ( 4 "context" 5 "encoding/json" 6 "io" 7 "net/http" 8 "net/url" 9 "strings" 10 "time" 11 12 "github.com/containerd/containerd/platforms" 13 "github.com/docker/distribution/reference" 14 "github.com/docker/docker/api/types/container" 15 "github.com/docker/docker/builder/dockerfile" 16 "github.com/docker/docker/builder/remotecontext" 17 "github.com/docker/docker/dockerversion" 18 "github.com/docker/docker/errdefs" 19 "github.com/docker/docker/image" 20 "github.com/docker/docker/layer" 21 "github.com/docker/docker/pkg/archive" 22 "github.com/docker/docker/pkg/progress" 23 "github.com/docker/docker/pkg/streamformatter" 24 "github.com/docker/docker/pkg/system" 25 specs "github.com/opencontainers/image-spec/specs-go/v1" 26 "github.com/pkg/errors" 27 ) 28 29 // ImportImage imports an image, getting the archived layer data either from 30 // inConfig (if src is "-"), or from a URI specified in src. Progress output is 31 // written to outStream. Repository and tag names can optionally be given in 32 // the repo and tag arguments, respectively. 33 func (i *ImageService) ImportImage(ctx context.Context, src string, repository string, platform *specs.Platform, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error { 34 var ( 35 rc io.ReadCloser 36 resp *http.Response 37 newRef reference.Named 38 ) 39 40 if repository != "" { 41 var err error 42 newRef, err = reference.ParseNormalizedNamed(repository) 43 if err != nil { 44 return errdefs.InvalidParameter(err) 45 } 46 if _, isCanonical := newRef.(reference.Canonical); isCanonical { 47 return errdefs.InvalidParameter(errors.New("cannot import digest reference")) 48 } 49 50 if tag != "" { 51 newRef, err = reference.WithTag(newRef, tag) 52 if err != nil { 53 return errdefs.InvalidParameter(err) 54 } 55 } 56 } 57 58 // Normalize platform - default to the operating system and architecture if not supplied. 59 if platform == nil { 60 p := platforms.DefaultSpec() 61 platform = &p 62 } 63 if !system.IsOSSupported(platform.OS) { 64 return errdefs.InvalidParameter(system.ErrNotSupportedOperatingSystem) 65 } 66 config, err := dockerfile.BuildFromConfig(ctx, &container.Config{}, changes, platform.OS) 67 if err != nil { 68 return err 69 } 70 if src == "-" { 71 rc = inConfig 72 } else { 73 inConfig.Close() 74 if len(strings.Split(src, "://")) == 1 { 75 src = "http://" + src 76 } 77 u, err := url.Parse(src) 78 if err != nil { 79 return errdefs.InvalidParameter(err) 80 } 81 82 resp, err = remotecontext.GetWithStatusError(u.String()) 83 if err != nil { 84 return err 85 } 86 outStream.Write(streamformatter.FormatStatus("", "Downloading from %s", u)) 87 progressOutput := streamformatter.NewJSONProgressOutput(outStream, true) 88 rc = progress.NewProgressReader(resp.Body, progressOutput, resp.ContentLength, "", "Importing") 89 } 90 91 defer rc.Close() 92 if len(msg) == 0 { 93 msg = "Imported from " + src 94 } 95 96 inflatedLayerData, err := archive.DecompressStream(rc) 97 if err != nil { 98 return err 99 } 100 l, err := i.layerStore.Register(inflatedLayerData, "") 101 if err != nil { 102 return err 103 } 104 defer layer.ReleaseAndLog(i.layerStore, l) 105 106 created := time.Now().UTC() 107 imgConfig, err := json.Marshal(&image.Image{ 108 V1Image: image.V1Image{ 109 DockerVersion: dockerversion.Version, 110 Config: config, 111 Architecture: platform.Architecture, 112 Variant: platform.Variant, 113 OS: platform.OS, 114 Created: created, 115 Comment: msg, 116 }, 117 RootFS: &image.RootFS{ 118 Type: "layers", 119 DiffIDs: []layer.DiffID{l.DiffID()}, 120 }, 121 History: []image.History{{ 122 Created: created, 123 Comment: msg, 124 }}, 125 }) 126 if err != nil { 127 return err 128 } 129 130 id, err := i.imageStore.Create(imgConfig) 131 if err != nil { 132 return err 133 } 134 135 // FIXME: connect with commit code and call refstore directly 136 if newRef != nil { 137 if err := i.TagImageWithReference(id, newRef); err != nil { 138 return err 139 } 140 } 141 142 i.LogImageEvent(id.String(), id.String(), "import") 143 outStream.Write(streamformatter.FormatStatus("", id.String())) 144 return nil 145 }