func postBuild(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if version < 1.3 { return fmt.Errorf("Multipart upload for build is no longer supported. Please upgrade your docker client.") } remoteURL := r.FormValue("remote") repoName := r.FormValue("t") rawSuppressOutput := r.FormValue("q") rawNoCache := r.FormValue("nocache") rawRm := r.FormValue("rm") repoName, tag := utils.ParseRepositoryTag(repoName) var context io.Reader if remoteURL == "" { context = r.Body } else if utils.IsGIT(remoteURL) { if !strings.HasPrefix(remoteURL, "git://") { remoteURL = "https://" + remoteURL } root, err := ioutil.TempDir("", "docker-build-git") if err != nil { return err } defer os.RemoveAll(root) if output, err := exec.Command("git", "clone", remoteURL, root).CombinedOutput(); err != nil { return fmt.Errorf("Error trying to use git: %s (%s)", err, output) } c, err := archive.Tar(root, archive.Bzip2) if err != nil { return err } context = c } else if utils.IsURL(remoteURL) { f, err := utils.Download(remoteURL, ioutil.Discard) if err != nil { return err } defer f.Body.Close() dockerFile, err := ioutil.ReadAll(f.Body) if err != nil { return err } c, err := MkBuildContext(string(dockerFile), nil) if err != nil { return err } context = c } suppressOutput, err := getBoolParam(rawSuppressOutput) if err != nil { return err } noCache, err := getBoolParam(rawNoCache) if err != nil { return err } rm, err := getBoolParam(rawRm) if err != nil { return err } b := NewBuildFile(srv, utils.NewWriteFlusher(w), !suppressOutput, !noCache, rm) id, err := b.Build(context) if err != nil { return fmt.Errorf("Error build: %s", err) } if repoName != "" { srv.runtime.repositories.Set(repoName, tag, id, false) } return nil }
func postBuild(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if version < 1.3 { return fmt.Errorf("Multipart upload for build is no longer supported. Please upgrade your docker client.") } remoteURL := r.FormValue("remote") repoName := r.FormValue("t") tag := "" if strings.Contains(repoName, ":") { remoteParts := strings.Split(repoName, ":") tag = remoteParts[1] repoName = remoteParts[0] } var context io.Reader if remoteURL == "" { context = r.Body } else if utils.IsGIT(remoteURL) { if !strings.HasPrefix(remoteURL, "git://") { remoteURL = "https://" + remoteURL } root, err := ioutil.TempDir("", "docker-build-git") if err != nil { return err } defer os.RemoveAll(root) if output, err := exec.Command("git", "clone", remoteURL, root).CombinedOutput(); err != nil { return fmt.Errorf("Error trying to use git: %s (%s)", err, output) } c, err := Tar(root, Bzip2) if err != nil { return err } context = c } else if utils.IsURL(remoteURL) { f, err := utils.Download(remoteURL, ioutil.Discard) if err != nil { return err } defer f.Body.Close() dockerFile, err := ioutil.ReadAll(f.Body) if err != nil { return err } c, err := mkBuildContext(string(dockerFile), nil) if err != nil { return err } context = c } b := NewBuildFile(srv, utils.NewWriteFlusher(w)) id, err := b.Build(context) if err != nil { fmt.Fprintf(w, "Error build: %s\n", err) return err } if repoName != "" { srv.runtime.repositories.Set(repoName, tag, id, false) } return nil }
func (cli *DockerCli) CmdBuild(args ...string) error { cmd := Subcmd("build", "[OPTIONS] PATH | URL | -", "Build a new container image from the source code at PATH") tag := cmd.String("t", "", "Tag to be applied to the resulting image in case of success") suppressOutput := cmd.Bool("q", false, "Suppress verbose build output") if err := cmd.Parse(args); err != nil { return nil } if cmd.NArg() != 1 { cmd.Usage() return nil } var ( context Archive isRemote bool err error ) if cmd.Arg(0) == "-" { // As a special case, 'docker build -' will build from an empty context with the // contents of stdin as a Dockerfile dockerfile, err := ioutil.ReadAll(cli.in) if err != nil { return err } context, err = mkBuildContext(string(dockerfile), nil) } else if utils.IsURL(cmd.Arg(0)) || utils.IsGIT(cmd.Arg(0)) { isRemote = true } else { context, err = Tar(cmd.Arg(0), Uncompressed) } var body io.Reader // Setup an upload progress bar // FIXME: ProgressReader shouldn't be this annoyning to use if context != nil { sf := utils.NewStreamFormatter(false) body = utils.ProgressReader(ioutil.NopCloser(context), 0, cli.err, sf.FormatProgress("Uploading context", "%v bytes%0.0s%0.0s"), sf) } // Upload the build context v := &url.Values{} v.Set("t", *tag) if *suppressOutput { v.Set("q", "1") } if isRemote { v.Set("remote", cmd.Arg(0)) } req, err := http.NewRequest("POST", fmt.Sprintf("/v%g/build?%s", APIVERSION, v.Encode()), body) if err != nil { return err } if context != nil { req.Header.Set("Content-Type", "application/tar") } dial, err := net.Dial(cli.proto, cli.addr) if err != nil { return err } clientconn := httputil.NewClientConn(dial, nil) resp, err := clientconn.Do(req) defer clientconn.Close() if err != nil { return err } defer resp.Body.Close() // Check for errors if resp.StatusCode < 200 || resp.StatusCode >= 400 { body, err := ioutil.ReadAll(resp.Body) if err != nil { return err } if len(body) == 0 { return fmt.Errorf("Error: %s", http.StatusText(resp.StatusCode)) } return fmt.Errorf("Error: %s", body) } // Output the result if _, err := io.Copy(cli.out, resp.Body); err != nil { return err } return nil }
func postBuild(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if version < 1.3 { return fmt.Errorf("Multipart upload for build is no longer supported. Please upgrade your docker client.") } var ( remoteURL = r.FormValue("remote") repoName = r.FormValue("t") rawSuppressOutput = r.FormValue("q") rawNoCache = r.FormValue("nocache") rawRm = r.FormValue("rm") authEncoded = r.Header.Get("X-Registry-Auth") authConfig = &auth.AuthConfig{} configFileEncoded = r.Header.Get("X-Registry-Config") configFile = &auth.ConfigFile{} tag string ) repoName, tag = utils.ParseRepositoryTag(repoName) // This block can be removed when API versions prior to 1.9 are deprecated. // Both headers will be parsed and sent along to the daemon, but if a non-empty // ConfigFile is present, any value provided as an AuthConfig directly will // be overridden. See BuildFile::CmdFrom for details. if version < 1.9 && authEncoded != "" { authJson := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded)) if err := json.NewDecoder(authJson).Decode(authConfig); err != nil { // for a pull it is not an error if no auth was given // to increase compatibility with the existing api it is defaulting to be empty authConfig = &auth.AuthConfig{} } } if configFileEncoded != "" { configFileJson := base64.NewDecoder(base64.URLEncoding, strings.NewReader(configFileEncoded)) if err := json.NewDecoder(configFileJson).Decode(configFile); err != nil { // for a pull it is not an error if no auth was given // to increase compatibility with the existing api it is defaulting to be empty configFile = &auth.ConfigFile{} } } var context io.Reader if remoteURL == "" { context = r.Body } else if utils.IsGIT(remoteURL) { if !strings.HasPrefix(remoteURL, "git://") { remoteURL = "https://" + remoteURL } root, err := ioutil.TempDir("", "docker-build-git") if err != nil { return err } defer os.RemoveAll(root) if output, err := exec.Command("git", "clone", remoteURL, root).CombinedOutput(); err != nil { return fmt.Errorf("Error trying to use git: %s (%s)", err, output) } c, err := archive.Tar(root, archive.Uncompressed) if err != nil { return err } context = c } else if utils.IsURL(remoteURL) { f, err := utils.Download(remoteURL) if err != nil { return err } defer f.Body.Close() dockerFile, err := ioutil.ReadAll(f.Body) if err != nil { return err } c, err := MkBuildContext(string(dockerFile), nil) if err != nil { return err } context = c } suppressOutput, err := getBoolParam(rawSuppressOutput) if err != nil { return err } noCache, err := getBoolParam(rawNoCache) if err != nil { return err } rm, err := getBoolParam(rawRm) if err != nil { return err } if version >= 1.8 { w.Header().Set("Content-Type", "application/json") } sf := utils.NewStreamFormatter(version >= 1.8) b := NewBuildFile(srv, &StdoutFormater{ Writer: utils.NewWriteFlusher(w), StreamFormatter: sf, }, &StderrFormater{ Writer: utils.NewWriteFlusher(w), StreamFormatter: sf, }, !suppressOutput, !noCache, rm, utils.NewWriteFlusher(w), sf, authConfig, configFile) id, err := b.Build(context) if err != nil { if sf.Used() { w.Write(sf.FormatError(err)) return nil } return fmt.Errorf("Error build: %s", err) } if repoName != "" { srv.runtime.repositories.Set(repoName, tag, id, false) } return nil }