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