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