func (srv *Server) ImagePull(localName string, tag string, out io.Writer, sf *utils.StreamFormatter, authConfig *auth.AuthConfig, metaHeaders map[string][]string, parallel bool) error { r, err := registry.NewRegistry(srv.runtime.root, authConfig, srv.HTTPRequestFactory(metaHeaders)) if err != nil { return err } if err := srv.poolAdd("pull", localName+":"+tag); err != nil { return err } defer srv.poolRemove("pull", localName+":"+tag) // Resolve the Repository name from fqn to endpoint + name endpoint, remoteName, err := registry.ResolveRepositoryName(localName) if err != nil { return err } if endpoint == auth.IndexServerAddress() { // If pull "index.docker.io/foo/bar", it's stored locally under "foo/bar" localName = remoteName } out = utils.NewWriteFlusher(out) err = srv.pullRepository(r, out, localName, remoteName, tag, endpoint, sf, parallel) if err == registry.ErrLoginRequired { return err } if err != nil { if err := srv.pullImage(r, out, remoteName, endpoint, nil, sf); err != nil { return err } return nil } return nil }
func (srv *Server) ImagePull(name string, tag string, out io.Writer, sf *utils.StreamFormatter, authConfig *auth.AuthConfig) error { r, err := registry.NewRegistry(srv.runtime.root, authConfig) if err != nil { return err } if err := srv.poolAdd("pull", name+":"+tag); err != nil { return err } defer srv.poolRemove("pull", name+":"+tag) // Resolve the Repository name from fqn to endpoint + name var endpoint string endpoint, name, err = registry.ResolveRepositoryName(name) if err != nil { return err } out = utils.NewWriteFlusher(out) err = srv.pullRepository(r, out, name, tag, endpoint, sf) if err != nil { if err := srv.pullImage(r, out, name, endpoint, nil, sf); err != nil { return err } return nil } return nil }
func (b *buildFile) CmdFrom(name string) error { image, err := b.runtime.Repositories().LookupImage(name) if err != nil { if b.runtime.Graph().IsNotExist(err) { remote, tag := utils.ParseRepositoryTag(name) pullRegistryAuth := b.authConfig if len(b.configFile.Configs) > 0 { // The request came with a full auth config file, we prefer to use that endpoint, _, err := registry.ResolveRepositoryName(remote) if err != nil { return err } resolvedAuth := b.configFile.ResolveAuthConfig(endpoint) pullRegistryAuth = &resolvedAuth } job := b.srv.Eng.Job("pull", remote, tag) job.SetenvBool("json", b.sf.Json()) job.SetenvBool("parallel", true) job.SetenvJson("authConfig", pullRegistryAuth) job.Stdout.Add(b.outOld) if err := job.Run(); err != nil { return err } image, err = b.runtime.Repositories().LookupImage(name) if err != nil { return err } } else { return err } } b.image = image.ID b.config = &runconfig.Config{} if image.Config != nil { b.config = image.Config } if b.config.Env == nil || len(b.config.Env) == 0 { b.config.Env = append(b.config.Env, "HOME=/", "PATH="+runtime.DefaultPathEnv) } // Process ONBUILD triggers if they exist if nTriggers := len(b.config.OnBuild); nTriggers != 0 { fmt.Fprintf(b.errStream, "# Executing %d build triggers\n", nTriggers) } for n, step := range b.config.OnBuild { splitStep := strings.Split(step, " ") stepInstruction := strings.ToUpper(strings.Trim(splitStep[0], " ")) switch stepInstruction { case "ONBUILD": return fmt.Errorf("Source image contains forbidden chained `ONBUILD ONBUILD` trigger: %s", step) case "MAINTAINER", "FROM": return fmt.Errorf("Source image contains forbidden %s trigger: %s", stepInstruction, step) } if err := b.BuildStep(fmt.Sprintf("onbuild-%d", n), step); err != nil { return err } } b.config.OnBuild = []string{} return nil }
func (cli *DockerCli) CmdPull(args ...string) error { cmd := Subcmd("pull", "NAME", "Pull an image or a repository from the registry") tag := cmd.String("t", "", "Download tagged image in repository") if err := cmd.Parse(args); err != nil { return nil } if cmd.NArg() != 1 { cmd.Usage() return nil } remote, parsedTag := utils.ParseRepositoryTag(cmd.Arg(0)) if *tag == "" { *tag = parsedTag } // Resolve the Repository name from fqn to endpoint + name endpoint, _, err := registry.ResolveRepositoryName(remote) if err != nil { return err } cli.LoadConfigFile() // Resolve the Auth config relevant for this server authConfig := cli.configFile.ResolveAuthConfig(endpoint) v := url.Values{} v.Set("fromImage", remote) v.Set("tag", *tag) pull := func(authConfig auth.AuthConfig) error { buf, err := json.Marshal(authConfig) if err != nil { return err } registryAuthHeader := []string{ base64.URLEncoding.EncodeToString(buf), } return cli.stream("POST", "/images/create?"+v.Encode(), nil, cli.out, map[string][]string{ "X-Registry-Auth": registryAuthHeader, }) } if err := pull(authConfig); err != nil { if err.Error() == registry.ErrLoginRequired.Error() { fmt.Fprintln(cli.out, "\nPlease login prior to push:") if err := cli.CmdLogin(endpoint); err != nil { return err } authConfig := cli.configFile.ResolveAuthConfig(endpoint) return pull(authConfig) } return err } return nil }
func (b *buildFile) CmdFrom(name string) error { image, err := b.runtime.repositories.LookupImage(name) if err != nil { if b.runtime.graph.IsNotExist(err) { remote, tag := utils.ParseRepositoryTag(name) pullRegistryAuth := b.authConfig if len(b.configFile.Configs) > 0 { // The request came with a full auth config file, we prefer to use that endpoint, _, err := registry.ResolveRepositoryName(remote) if err != nil { return err } resolvedAuth := b.configFile.ResolveAuthConfig(endpoint) pullRegistryAuth = &resolvedAuth } job := b.srv.Eng.Job("pull", remote, tag) job.SetenvBool("json", b.sf.Json()) job.SetenvBool("parallel", true) job.SetenvJson("authConfig", pullRegistryAuth) job.Stdout.Add(b.outOld) if err := job.Run(); err != nil { return err } image, err = b.runtime.repositories.LookupImage(name) if err != nil { return err } } else { return err } } b.image = image.ID b.config = &runconfig.Config{} if image.Config != nil { b.config = image.Config } if b.config.Env == nil || len(b.config.Env) == 0 { b.config.Env = append(b.config.Env, "HOME=/", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin") } // Process ONBUILD triggers if they exist if nTriggers := len(b.config.OnBuild); nTriggers != 0 { fmt.Fprintf(b.errStream, "# Executing %d build triggers\n", nTriggers) } for n, step := range b.config.OnBuild { if err := b.BuildStep(fmt.Sprintf("onbuild-%d", n), step); err != nil { return err } } b.config.OnBuild = []string{} return nil }
func (b *buildFile) CmdFrom(name string) error { image, err := b.runtime.repositories.LookupImage(name) if err != nil { if b.runtime.graph.IsNotExist(err) { remote, tag := utils.ParseRepositoryTag(name) pullRegistryAuth := b.authConfig if len(b.configFile.Configs) > 0 { // The request came with a full auth config file, we prefer to use that endpoint, _, err := registry.ResolveRepositoryName(remote) if err != nil { return err } resolvedAuth := b.configFile.ResolveAuthConfig(endpoint) pullRegistryAuth = &resolvedAuth } job := b.srv.Eng.Job("pull", remote, tag) job.SetenvBool("json", b.sf.Json()) job.SetenvBool("parallel", true) job.SetenvJson("authConfig", pullRegistryAuth) job.Stdout.Add(b.outOld) if err := job.Run(); err != nil { return err } image, err = b.runtime.repositories.LookupImage(name) if err != nil { return err } } else { return err } } b.image = image.ID b.config = &Config{} if image.Config != nil { b.config = image.Config } if b.config.Env == nil || len(b.config.Env) == 0 { b.config.Env = append(b.config.Env, "HOME=/", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin") } return nil }
// FIXME: Allow to interrupt current push when new push of same image is done. func (srv *Server) ImagePush(localName string, out io.Writer, sf *utils.StreamFormatter, authConfig *auth.AuthConfig, metaHeaders map[string][]string) error { if err := srv.poolAdd("push", localName); err != nil { return err } defer srv.poolRemove("push", localName) // Resolve the Repository name from fqn to endpoint + name endpoint, remoteName, err := registry.ResolveRepositoryName(localName) if err != nil { return err } out = utils.NewWriteFlusher(out) img, err := srv.runtime.graph.Get(localName) r, err2 := registry.NewRegistry(srv.runtime.root, authConfig, srv.HTTPRequestFactory(metaHeaders)) if err2 != nil { return err2 } if err != nil { reposLen := len(srv.runtime.repositories.Repositories[localName]) out.Write(sf.FormatStatus("", "The push refers to a repository [%s] (len: %d)", localName, reposLen)) // If it fails, try to get the repository if localRepo, exists := srv.runtime.repositories.Repositories[localName]; exists { if err := srv.pushRepository(r, out, localName, remoteName, localRepo, endpoint, sf); err != nil { return err } return nil } return err } var token []string out.Write(sf.FormatStatus("", "The push refers to an image: [%s]", localName)) if _, err := srv.pushImage(r, out, remoteName, img.ID, endpoint, token, sf); err != nil { return err } return nil }
func (cli *DockerCli) CmdPush(args ...string) error { cmd := Subcmd("push", "NAME", "Push an image or a repository to the registry") if err := cmd.Parse(args); err != nil { return nil } name := cmd.Arg(0) if name == "" { cmd.Usage() return nil } cli.LoadConfigFile() // Resolve the Repository name from fqn to endpoint + name endpoint, _, err := registry.ResolveRepositoryName(name) if err != nil { return err } // Resolve the Auth config relevant for this server authConfig := cli.configFile.ResolveAuthConfig(endpoint) // If we're not using a custom registry, we know the restrictions // applied to repository names and can warn the user in advance. // Custom repositories can have different rules, and we must also // allow pushing by image ID. if len(strings.SplitN(name, "/", 2)) == 1 { username := cli.configFile.Configs[auth.IndexServerAddress()].Username if username == "" { username = "******" } return fmt.Errorf("Impossible to push a \"root\" repository. Please rename your repository in <user>/<repo> (ex: %s/%s)", username, name) } v := url.Values{} push := func(authConfig auth.AuthConfig) error { buf, err := json.Marshal(authConfig) if err != nil { return err } registryAuthHeader := []string{ base64.URLEncoding.EncodeToString(buf), } return cli.stream("POST", "/images/"+name+"/push?"+v.Encode(), nil, cli.out, map[string][]string{ "X-Registry-Auth": registryAuthHeader, }) } if err := push(authConfig); err != nil { if err.Error() == registry.ErrLoginRequired.Error() { fmt.Fprintln(cli.out, "\nPlease login prior to push:") if err := cli.CmdLogin(endpoint); err != nil { return err } authConfig := cli.configFile.ResolveAuthConfig(endpoint) return push(authConfig) } return err } return nil }
func (cli *DockerCli) CmdRun(args ...string) error { config, hostConfig, cmd, err := ParseRun(args, nil) if err != nil { return err } if config.Image == "" { cmd.Usage() return nil } var containerIDFile *os.File if len(hostConfig.ContainerIDFile) > 0 { if _, err := ioutil.ReadFile(hostConfig.ContainerIDFile); err == nil { return fmt.Errorf("cid file found, make sure the other container isn't running or delete %s", hostConfig.ContainerIDFile) } containerIDFile, err = os.Create(hostConfig.ContainerIDFile) if err != nil { return fmt.Errorf("failed to create the container ID file: %s", err) } defer containerIDFile.Close() } //create the container body, statusCode, err := cli.call("POST", "/containers/create", config) //if image not found try to pull it if statusCode == 404 { _, tag := utils.ParseRepositoryTag(config.Image) if tag == "" { tag = DEFAULTTAG } fmt.Fprintf(cli.err, "Unable to find image '%s' (tag: %s) locally\n", config.Image, tag) v := url.Values{} repos, tag := utils.ParseRepositoryTag(config.Image) v.Set("fromImage", repos) v.Set("tag", tag) // Resolve the Repository name from fqn to endpoint + name var endpoint string endpoint, _, err = registry.ResolveRepositoryName(repos) if err != nil { return err } // Load the auth config file, to be able to pull the image cli.LoadConfigFile() // Resolve the Auth config relevant for this server authConfig := cli.configFile.ResolveAuthConfig(endpoint) buf, err := json.Marshal(authConfig) if err != nil { return err } registryAuthHeader := []string{ base64.URLEncoding.EncodeToString(buf), } err = cli.stream("POST", "/images/create?"+v.Encode(), nil, cli.err, map[string][]string{ "X-Registry-Auth": registryAuthHeader, }) if err != nil { return err } body, _, err = cli.call("POST", "/containers/create", config) if err != nil { return err } } if err != nil { return err } runResult := &APIRun{} err = json.Unmarshal(body, runResult) if err != nil { return err } for _, warning := range runResult.Warnings { fmt.Fprintf(cli.err, "WARNING: %s\n", warning) } if len(hostConfig.ContainerIDFile) > 0 { if _, err = containerIDFile.WriteString(runResult.ID); err != nil { return fmt.Errorf("failed to write the container ID to the file: %s", err) } } //start the container if _, _, err = cli.call("POST", "/containers/"+runResult.ID+"/start", hostConfig); err != nil { return err } var wait chan struct{} if !config.AttachStdout && !config.AttachStderr { // Make this asynchrone in order to let the client write to stdin before having to read the ID wait = make(chan struct{}) go func() { defer close(wait) fmt.Fprintf(cli.out, "%s\n", runResult.ID) }() } if config.AttachStdin || config.AttachStdout || config.AttachStderr { if config.Tty { if err := cli.monitorTtySize(runResult.ID); err != nil { utils.Debugf("Error monitoring TTY size: %s\n", err) } } v := url.Values{} v.Set("logs", "1") v.Set("stream", "1") var out io.Writer if config.AttachStdin { v.Set("stdin", "1") } if config.AttachStdout { v.Set("stdout", "1") out = cli.out } if config.AttachStderr { v.Set("stderr", "1") out = cli.out } signals := make(chan os.Signal, 1) signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM) go func() { for sig := range signals { fmt.Printf("\nReceived signal: %s; cleaning up\n", sig) if err := cli.CmdStop("-t", "4", runResult.ID); err != nil { fmt.Printf("failed to stop container: %v", err) } } }() if err := cli.hijack("POST", "/containers/"+runResult.ID+"/attach?"+v.Encode(), config.Tty, cli.in, out); err != nil { utils.Debugf("Error hijack: %s", err) return err } } if !config.AttachStdout && !config.AttachStderr { // Detached mode <-wait } else { status, err := getExitCode(cli, runResult.ID) if err != nil { return err } if status != 0 { return &utils.StatusError{Status: status} } } return nil }