// Match is exported func (image *Image) Match(IDOrName string, matchTag bool) bool { size := len(IDOrName) // TODO: prefix match can cause false positives with image names if image.Id == IDOrName || (size > 2 && strings.HasPrefix(image.Id, IDOrName)) { return true } repoName, tag := parsers.ParseRepositoryTag(IDOrName) // match repotag for _, imageRepoTag := range image.RepoTags { imageRepoName, imageTag := parsers.ParseRepositoryTag(imageRepoTag) if matchTag == false && imageRepoName == repoName { return true } if imageRepoName == repoName && (imageTag == tag || tag == "") { return true } } // match repodigests for _, imageDigest := range image.RepoDigests { imageRepoName, imageDigest := parsers.ParseRepositoryTag(imageDigest) if matchTag == false && imageRepoName == repoName { return true } if imageRepoName == repoName && (imageDigest == tag || tag == "") { return true } } return false }
// Creates an image from Pull or from Import func postImagesCreate(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := parseForm(r); err != nil { return err } var ( image = r.Form.Get("fromImage") repo = r.Form.Get("repo") tag = r.Form.Get("tag") job *engine.Job ) authEncoded := r.Header.Get("X-Registry-Auth") authConfig := ®istry.AuthConfig{} if 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 = ®istry.AuthConfig{} } } if image != "" { //pull if tag == "" { image, tag = parsers.ParseRepositoryTag(image) } metaHeaders := map[string][]string{} for k, v := range r.Header { if strings.HasPrefix(k, "X-Meta-") { metaHeaders[k] = v } } job = eng.Job("pull", image, tag) job.SetenvBool("parallel", version.GreaterThan("1.3")) job.SetenvJson("metaHeaders", metaHeaders) job.SetenvJson("authConfig", authConfig) } else { //import if tag == "" { repo, tag = parsers.ParseRepositoryTag(repo) } job = eng.Job("import", r.Form.Get("fromSrc"), repo, tag) job.Stdin.Add(r.Body) job.SetenvList("changes", r.Form["changes"]) } if version.GreaterThan("1.0") { job.SetenvBool("json", true) streamJSON(job, w, true) } else { job.Stdout.Add(utils.NewWriteFlusher(w)) } if err := job.Run(); err != nil { if !job.Stdout.Used() { return err } sf := utils.NewStreamFormatter(version.GreaterThan("1.0")) w.Write(sf.FormatError(err)) } return nil }
func (c *Container) Stage() *Container { c.Parse() if c.Err != nil { return c } client, err := NewClient(c.dockerHost) if err != nil { c.Err = err return c } _, err = client.InspectImage(c.Config.Image) if err == dockerClient.ErrNoSuchImage { toPull := c.Config.Image _, tag := parsers.ParseRepositoryTag(toPull) if tag == "" { toPull += ":latest" } c.Err = client.PullImage(dockerClient.PullImageOptions{ Repository: toPull, OutputStream: os.Stdout, }, dockerClient.AuthConfiguration{}) } else if err != nil { log.Errorf("Failed to stage: %s: %v", c.Config.Image, err) c.Err = err } return c }
// Pull tells Docker to pull image referenced by `name`. func (d Docker) Pull(name string) (*image.Image, error) { remote, tag := parsers.ParseRepositoryTag(name) if tag == "" { tag = "latest" } pullRegistryAuth := &cliconfig.AuthConfig{} if len(d.AuthConfigs) > 0 { // The request came with a full auth config file, we prefer to use that repoInfo, err := d.Daemon.RegistryService.ResolveRepository(remote) if err != nil { return nil, err } resolvedConfig := registry.ResolveAuthConfig( &cliconfig.ConfigFile{AuthConfigs: d.AuthConfigs}, repoInfo.Index, ) pullRegistryAuth = &resolvedConfig } imagePullConfig := &graph.ImagePullConfig{ AuthConfig: pullRegistryAuth, OutStream: ioutils.NopWriteCloser(d.OutOld), } if err := d.Daemon.PullImage(remote, tag, imagePullConfig); err != nil { return nil, err } return d.Daemon.GetImage(name) }
func (cli *DockerCli) pullImageCustomOut(image string, out io.Writer) error { v := url.Values{} repos, tag := parsers.ParseRepositoryTag(image) // pull only the image tagged 'latest' if no tag was specified if tag == "" { tag = graph.DEFAULTTAG } v.Set("fromImage", repos) v.Set("tag", tag) // Resolve the Repository name from fqn to RepositoryInfo repoInfo, err := registry.ParseRepositoryInfo(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(repoInfo.Index) buf, err := json.Marshal(authConfig) if err != nil { return err } registryAuthHeader := []string{ base64.URLEncoding.EncodeToString(buf), } if err = cli.stream("POST", "/images/create?"+v.Encode(), nil, out, map[string][]string{"X-Registry-Auth": registryAuthHeader}); err != nil { return err } return nil }
// CmdPull pulls an image or a repository from the registry. // // Usage: docker pull [OPTIONS] IMAGENAME[:TAG|@DIGEST] func (cli *DockerCli) CmdPull(args ...string) error { cmd := cli.Subcmd("pull", "NAME[:TAG|@DIGEST]", "Pull an image or a repository from the registry", true) allTags := cmd.Bool([]string{"a", "-all-tags"}, false, "Download all tagged images in the repository") cmd.Require(flag.Exact, 1) cmd.ParseFlags(args, true) var ( v = url.Values{} remote = cmd.Arg(0) newRemote = remote ) taglessRemote, tag := parsers.ParseRepositoryTag(remote) if tag == "" && !*allTags { newRemote = utils.ImageReference(taglessRemote, graph.DEFAULTTAG) } if tag != "" && *allTags { return fmt.Errorf("tag can't be used with --all-tags/-a") } v.Set("fromImage", newRemote) // Resolve the Repository name from fqn to RepositoryInfo repoInfo, err := registry.ParseRepositoryInfo(taglessRemote) if err != nil { return err } cli.LoadConfigFile() _, _, err = cli.clientRequestAttemptLogin("POST", "/images/create?"+v.Encode(), nil, cli.out, repoInfo.Index, "pull") return err }
// CmdCommit creates a new image from a container's changes. // // Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]] func (cli *DockerCli) CmdCommit(args ...string) error { cmd := cli.Subcmd("commit", "CONTAINER [REPOSITORY[:TAG]]", "Create a new image from a container's changes", true) flPause := cmd.Bool([]string{"p", "-pause"}, true, "Pause container during commit") flComment := cmd.String([]string{"m", "-message"}, "", "Commit message") flAuthor := cmd.String([]string{"a", "#author", "-author"}, "", "Author (e.g., \"John Hannibal Smith <*****@*****.**>\")") flChanges := opts.NewListOpts(nil) cmd.Var(&flChanges, []string{"c", "-change"}, "Apply Dockerfile instruction to the created image") // FIXME: --run is deprecated, it will be replaced with inline Dockerfile commands. flConfig := cmd.String([]string{"#run", "#-run"}, "", "This option is deprecated and will be removed in a future version in favor of inline Dockerfile-compatible commands") cmd.Require(flag.Max, 2) cmd.Require(flag.Min, 1) utils.ParseFlags(cmd, args, true) var ( name = cmd.Arg(0) repository, tag = parsers.ParseRepositoryTag(cmd.Arg(1)) ) //Check if the given image name can be resolved if repository != "" { if err := registry.ValidateRepositoryName(repository); err != nil { return err } } v := url.Values{} v.Set("container", name) v.Set("repo", repository) v.Set("tag", tag) v.Set("comment", *flComment) v.Set("author", *flAuthor) for _, change := range flChanges.GetAll() { v.Add("changes", change) } if *flPause != true { v.Set("pause", "0") } var ( config *runconfig.Config env engine.Env ) if *flConfig != "" { config = &runconfig.Config{} if err := json.Unmarshal([]byte(*flConfig), config); err != nil { return err } } stream, _, err := cli.call("POST", "/commit?"+v.Encode(), config, nil) if err != nil { return err } if err := env.Decode(stream); err != nil { return err } fmt.Fprintf(cli.out, "%s\n", env.Get("Id")) return nil }
func (c *Container) pull(image string) error { taglessRemote, tag := parsers.ParseRepositoryTag(image) if tag == "" { image = utils.ImageReference(taglessRemote, DefaultTag) } repoInfo, err := registry.ParseRepositoryInfo(taglessRemote) if err != nil { return err } authConfig := cliconfig.AuthConfig{} if c.service.context.ConfigFile != nil && repoInfo != nil && repoInfo.Index != nil { authConfig = registry.ResolveAuthConfig(c.service.context.ConfigFile, repoInfo.Index) } err = c.client.PullImage( dockerclient.PullImageOptions{ Repository: image, OutputStream: os.Stderr, // TODO maybe get the stream from some configured place }, dockerclient.AuthConfiguration{ Username: authConfig.Username, Password: authConfig.Password, Email: authConfig.Email, }, ) if err != nil { logrus.Errorf("Failed to pull image %s: %v", image, err) } return err }
// sanitizeRepoAndTags parses the raw "t" parameter received from the client // to a slice of repoAndTag. // It also validates each repoName and tag. func sanitizeRepoAndTags(names []string) ([]repoAndTag, error) { var ( repoAndTags []repoAndTag // This map is used for deduplicating the "-t" paramter. uniqNames = make(map[string]struct{}) ) for _, repo := range names { name, tag := parsers.ParseRepositoryTag(repo) if name == "" { continue } if err := registry.ValidateRepositoryName(name); err != nil { return nil, err } nameWithTag := name if len(tag) > 0 { if err := tags.ValidateTagName(tag); err != nil { return nil, err } nameWithTag += ":" + tag } else { nameWithTag += ":" + tags.DefaultTag } if _, exists := uniqNames[nameWithTag]; !exists { uniqNames[nameWithTag] = struct{}{} repoAndTags = append(repoAndTags, repoAndTag{repo: name, tag: tag}) } } return repoAndTags, nil }
func lookupID(s *graph.TagStore, name string) string { s.Lock() defer s.Unlock() repo, tag := parsers.ParseRepositoryTag(name) if r, exists := s.Repositories[repo]; exists { if tag == "" { tag = "latest" } if id, exists := r[tag]; exists { return id } } if r, exists := s.Repositories[registry.IndexName+"/"+repo]; exists { if tag == "" { tag = "latest" } if id, exists := r[tag]; exists { return id } } names := strings.Split(name, "/") if len(names) > 1 { if r, exists := s.Repositories[strings.Join(names[1:], "/")]; exists { if tag == "" { tag = "latest" } if id, exists := r[tag]; exists { return id } } } return "" }
// Filter returns a new sequence of Images filtered to only the images that // matched the filtering paramters func (images Images) Filter(opts ImageFilterOptions) Images { includeAll := func(image *Image) bool { // TODO: this is wrong if RepoTags == [] return opts.All || (len(image.RepoTags) != 0 && image.RepoTags[0] != "<none>:<none>") } includeFilter := func(image *Image) bool { if opts.Filters == nil { return true } return opts.Filters.MatchKVList("label", image.Labels) } includeRepoFilter := func(image *Image) bool { if opts.NameFilter == "" { return true } for _, repoTag := range image.RepoTags { repoName, _ := parsers.ParseRepositoryTag(repoTag) if repoTag == opts.NameFilter || repoName == opts.NameFilter { return true } } return false } filtered := make([]*Image, 0, len(images)) for _, image := range images { if includeAll(image) && includeFilter(image) && includeRepoFilter(image) { filtered = append(filtered, image) } } return filtered }
// ContainerCreate takes configs and creates a container. func (daemon *Daemon) ContainerCreate(params *ContainerCreateConfig) (types.ContainerCreateResponse, error) { if params.Config == nil { return types.ContainerCreateResponse{}, derr.ErrorCodeEmptyConfig } warnings, err := daemon.verifyContainerSettings(params.HostConfig, params.Config) if err != nil { return types.ContainerCreateResponse{"", warnings}, err } daemon.adaptContainerSettings(params.HostConfig, params.AdjustCPUShares) container, err := daemon.create(params) if err != nil { if daemon.Graph().IsNotExist(err, params.Config.Image) { if strings.Contains(params.Config.Image, "@") { return types.ContainerCreateResponse{"", warnings}, derr.ErrorCodeNoSuchImageHash.WithArgs(params.Config.Image) } img, tag := parsers.ParseRepositoryTag(params.Config.Image) if tag == "" { tag = tags.DefaultTag } return types.ContainerCreateResponse{"", warnings}, derr.ErrorCodeNoSuchImageTag.WithArgs(img, tag) } return types.ContainerCreateResponse{"", warnings}, err } return types.ContainerCreateResponse{container.ID, warnings}, nil }
func (cli Docker) SendCmdPull(image string, imagePullConfig *graph.ImagePullConfig) ([]byte, int, error) { // We need to create a container via an image object. If the image // is not stored locally, so we need to pull the image from the Docker HUB. // Get a Repository name and tag name from the argument, but be careful // with the Repository name with a port number. For example: // localdomain:5000/samba/hipache:latest repository, tag := parsers.ParseRepositoryTag(image) if err := registry.ValidateRepositoryName(repository); err != nil { return nil, -1, err } if len(tag) > 0 { if err := tags.ValidateTagName(tag); err != nil { return nil, -1, err } } else { tag = tags.DefaultTag } glog.V(3).Infof("The Repository is %s, and the tag is %s", repository, tag) glog.V(3).Info("pull the image from the repository!") err := cli.daemon.Repositories().Pull(repository, tag, imagePullConfig) if err != nil { return nil, -1, err } return nil, 200, nil }
func (c *ImageService) Pull(image string) error { name, tag := parsers.ParseRepositoryTag(image) if len(tag) == 0 { tag = DEFAULTTAG } return c.PullTag(name, tag) }
func (daemon *Daemon) ContainerCreate(name string, config *runconfig.Config, hostConfig *runconfig.HostConfig) (string, []string, error) { if config == nil { return "", nil, fmt.Errorf("Config cannot be empty in order to create a container") } daemon.adaptContainerSettings(hostConfig) warnings, err := daemon.verifyContainerSettings(hostConfig, config) if err != nil { return "", warnings, err } container, buildWarnings, err := daemon.Create(config, hostConfig, name) if err != nil { if daemon.Graph().IsNotExist(err, config.Image) { _, tag := parsers.ParseRepositoryTag(config.Image) if tag == "" { tag = graph.DefaultTag } return "", warnings, fmt.Errorf("No such image: %s (tag: %s)", config.Image, tag) } return "", warnings, err } warnings = append(warnings, buildWarnings...) return container.ID, warnings, nil }
// PullImage invokes 'rkt fetch' to download an aci. // TODO(yifan): Now we only support docker images, this should be changed // once the format of image is landed, see: // // https://github.com/GoogleCloudPlatform/kubernetes/issues/7203 // func (r *runtime) PullImage(image kubecontainer.ImageSpec, pullSecrets []api.Secret) error { img := image.Image // TODO(yifan): The credential operation is a copy from dockertools package, // Need to resolve the code duplication. repoToPull, tag := parsers.ParseRepositoryTag(img) // If no tag was specified, use the default "latest". if len(tag) == 0 { tag = "latest" } keyring, err := credentialprovider.MakeDockerKeyring(pullSecrets, r.dockerKeyring) if err != nil { return err } creds, ok := keyring.Lookup(repoToPull) if !ok { glog.V(1).Infof("Pulling image %s without credentials", img) } // Let's update a json. // TODO(yifan): Find a way to feed this to rkt. if err := r.writeDockerAuthConfig(img, creds); err != nil { return err } output, err := r.runCommand("fetch", dockerPrefix+img) if err != nil { return fmt.Errorf("rkt: Failed to fetch image: %v:", output) } return nil }
// LookupImage returns pointer to an Image struct corresponding to the given // name. The name can include an optional tag; otherwise the default tag will // be used. func (store *TagStore) LookupImage(name string) (*image.Image, error) { repoName, ref := parsers.ParseRepositoryTag(name) if ref == "" { ref = tags.DefaultTag } var ( err error img *image.Image ) img, err = store.getImage(repoName, ref) if err != nil { return nil, err } if img != nil { return img, nil } // name must be an image ID. store.Lock() defer store.Unlock() if img, err = store.graph.Get(name); err != nil { return nil, err } return img, nil }
// CmdPush pushes an image or repository to the registry. // // Usage: docker push NAME[:TAG] func (cli *DockerCli) CmdPush(args ...string) error { cmd := cli.Subcmd("push", []string{"NAME[:TAG]"}, "Push an image or a repository to a registry", true) cmd.Require(flag.Exact, 1) cmd.ParseFlags(args, true) name := cmd.Arg(0) remote, tag := parsers.ParseRepositoryTag(name) // Resolve the Repository name from fqn to RepositoryInfo repoInfo, err := registry.ParseRepositoryInfo(remote) if err != nil { return err } // Resolve the Auth config relevant for this server authConfig := registry.ResolveAuthConfig(cli.configFile, repoInfo.Index) // 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 repoInfo.Official { username := authConfig.Username if username == "" { username = "******" } return fmt.Errorf("You cannot push a \"root\" repository. Please rename your repository to <user>/<repo> (ex: %s/%s)", username, repoInfo.LocalName) } v := url.Values{} v.Set("tag", tag) _, _, err = cli.clientRequestAttemptLogin("POST", "/images/"+remote+"/push?"+v.Encode(), nil, cli.out, repoInfo.Index, "push") return err }
func (store *TagStore) LookupImage(name string) (*image.Image, error) { // FIXME: standardize on returning nil when the image doesn't exist, and err for everything else // (so we can pass all errors here) repoName, ref := parsers.ParseRepositoryTag(name) if ref == "" { ref = DEFAULTTAG } var ( err error img *image.Image ) img, err = store.GetImage(repoName, ref) if err != nil { return nil, err } if img != nil { return img, err } // name must be an image ID. store.Lock() defer store.Unlock() if img, err = store.graph.Get(name); err != nil { return nil, err } return img, nil }
func (b *Builder) pullImage(name string) (*imagepkg.Image, error) { remote, tag := parsers.ParseRepositoryTag(name) if tag == "" { tag = "latest" } job := b.Engine.Job("pull", remote, tag) pullRegistryAuth := b.AuthConfig if len(b.AuthConfigFile.Configs) > 0 { // The request came with a full auth config file, we prefer to use that repoInfo, err := registry.ResolveRepositoryInfo(job, remote) if err != nil { return nil, err } resolvedAuth := b.AuthConfigFile.ResolveAuthConfig(repoInfo.Index) pullRegistryAuth = &resolvedAuth } job.SetenvBool("json", b.StreamFormatter.Json()) job.SetenvBool("parallel", true) job.SetenvJson("authConfig", pullRegistryAuth) job.Stdout.Add(ioutils.NopWriteCloser(b.OutOld)) if err := job.Run(); err != nil { return nil, err } image, err := b.Daemon.Repositories().LookupImage(name) if err != nil { return nil, err } return image, nil }
// CmdTag tags an image into a repository. // // Usage: docker tag [OPTIONS] IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG] func (cli *DockerCli) CmdTag(args ...string) error { cmd := cli.Subcmd("tag", "IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG]", "Tag an image into a repository", true) force := cmd.Bool([]string{"f", "#force", "-force"}, false, "Force") cmd.Require(flag.Exact, 2) utils.ParseFlags(cmd, args, true) var ( repository, tag = parsers.ParseRepositoryTag(cmd.Arg(1)) v = url.Values{} ) //Check if the given image name can be resolved if err := registry.ValidateRepositoryName(repository); err != nil { return err } v.Set("repo", repository) v.Set("tag", tag) if *force { v.Set("force", "1") } if _, _, err := readBody(cli.call("POST", "/images/"+cmd.Arg(0)+"/tag?"+v.Encode(), nil, nil)); err != nil { return err } return nil }
func (c *Container) pull(image string) error { taglessRemote, tag := parsers.ParseRepositoryTag(image) if tag == "" { image = utils.ImageReference(taglessRemote, tags.DEFAULTTAG) } repoInfo, err := registry.ParseRepositoryInfo(taglessRemote) if err != nil { return err } authConfig := cliconfig.AuthConfig{} if c.service.context.ConfigFile != nil && repoInfo != nil && repoInfo.Index != nil { authConfig = registry.ResolveAuthConfig(c.service.context.ConfigFile, repoInfo.Index) } err = c.client.PullImage(image, &dockerclient.AuthConfig{ Username: authConfig.Username, Password: authConfig.Password, Email: authConfig.Email, }) if err != nil { logrus.Errorf("Failed to pull image %s: %v", image, err) } return err }
// ContainerCreate takes configs and creates a container. func (daemon *Daemon) ContainerCreate(name string, config *runconfig.Config, hostConfig *runconfig.HostConfig, adjustCPUShares bool) (*Container, []string, error) { if config == nil { return nil, nil, fmt.Errorf("Config cannot be empty in order to create a container") } warnings, err := daemon.verifyContainerSettings(hostConfig, config) if err != nil { return nil, warnings, err } daemon.adaptContainerSettings(hostConfig, adjustCPUShares) container, buildWarnings, err := daemon.Create(config, hostConfig, name) if err != nil { if daemon.Graph().IsNotExist(err, config.Image) { if strings.Contains(config.Image, "@") { return nil, warnings, fmt.Errorf("No such image: %s", config.Image) } img, tag := parsers.ParseRepositoryTag(config.Image) if tag == "" { tag = tags.DefaultTag } return nil, warnings, fmt.Errorf("No such image: %s:%s", img, tag) } return nil, warnings, err } warnings = append(warnings, buildWarnings...) return container, warnings, nil }
func (daemon *Daemon) ContainerCreate(name string, config *runconfig.Config, hostConfig *runconfig.HostConfig) (string, []string, error) { warnings, err := daemon.verifyHostConfig(hostConfig) if err != nil { return "", warnings, err } // The check for a valid workdir path is made on the server rather than in the // client. This is because we don't know the type of path (Linux or Windows) // to validate on the client. if config.WorkingDir != "" && !filepath.IsAbs(config.WorkingDir) { return "", warnings, fmt.Errorf("The working directory '%s' is invalid. It needs to be an absolute path.", config.WorkingDir) } container, buildWarnings, err := daemon.Create(config, hostConfig, name) if err != nil { if daemon.Graph().IsNotExist(err, config.Image) { _, tag := parsers.ParseRepositoryTag(config.Image) if tag == "" { tag = graph.DEFAULTTAG } return "", warnings, fmt.Errorf("No such image: %s (tag: %s)", config.Image, tag) } return "", warnings, err } container.LogEvent("create") warnings = append(warnings, buildWarnings...) return container.ID, warnings, nil }
// ContainerCreate takes configs and creates a container. func (daemon *Daemon) ContainerCreate(ctx context.Context, name string, config *runconfig.Config, hostConfig *runconfig.HostConfig, adjustCPUShares bool) (*Container, []string, error) { if config == nil { return nil, nil, derr.ErrorCodeEmptyConfig } warnings, err := daemon.verifyContainerSettings(ctx, hostConfig, config) if err != nil { return nil, warnings, err } daemon.adaptContainerSettings(hostConfig, adjustCPUShares) container, buildWarnings, err := daemon.Create(ctx, config, hostConfig, name) if err != nil { if daemon.Graph(ctx).IsNotExist(err, config.Image) { if strings.Contains(config.Image, "@") { return nil, warnings, derr.ErrorCodeNoSuchImageHash.WithArgs(config.Image) } img, tag := parsers.ParseRepositoryTag(config.Image) if tag == "" { tag = tags.DefaultTag } return nil, warnings, derr.ErrorCodeNoSuchImageTag.WithArgs(img, tag) } return nil, warnings, err } warnings = append(warnings, buildWarnings...) return container, warnings, nil }
func (b *Builder) pullImage(name string) (*imagepkg.Image, error) { remote, tag := parsers.ParseRepositoryTag(name) if tag == "" { tag = "latest" } pullRegistryAuth := b.AuthConfig if len(b.ConfigFile.AuthConfigs) > 0 { // The request came with a full auth config file, we prefer to use that repoInfo, err := b.Daemon.RegistryService.ResolveRepository(remote) if err != nil { return nil, err } resolvedAuth := registry.ResolveAuthConfig(b.ConfigFile, repoInfo.Index) pullRegistryAuth = &resolvedAuth } imagePullConfig := &graph.ImagePullConfig{ AuthConfig: pullRegistryAuth, OutStream: ioutils.NopWriteCloser(b.OutOld), } if err := b.Daemon.Repositories().Pull(remote, tag, imagePullConfig); err != nil { return nil, err } image, err := b.Daemon.Repositories().LookupImage(name) if err != nil { return nil, err } return image, nil }
// CmdSearch searches the Docker Hub for images. // // Usage: docker search [OPTIONS] TERM func (cli *DockerCli) CmdSearch(args ...string) error { cmd := cli.Subcmd("search", []string{"TERM"}, "Search the Docker Hub for images", true) noTrunc := cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Don't truncate output") trusted := cmd.Bool([]string{"#t", "#trusted", "#-trusted"}, false, "Only show trusted builds") automated := cmd.Bool([]string{"-automated"}, false, "Only show automated builds") stars := cmd.Uint([]string{"s", "#stars", "-stars"}, 0, "Only displays with at least x stars") cmd.Require(flag.Exact, 1) cmd.ParseFlags(args, true) name := cmd.Arg(0) v := url.Values{} v.Set("term", name) // Resolve the Repository name from fqn to hostname + name taglessRemote, _ := parsers.ParseRepositoryTag(name) repoInfo, err := registry.ParseRepositoryInfo(taglessRemote) if err != nil { return err } rdr, _, err := cli.clientRequestAttemptLogin("GET", "/images/search?"+v.Encode(), nil, nil, repoInfo.Index, "search") if err != nil { return err } defer rdr.Close() results := ByStars{} if err := json.NewDecoder(rdr).Decode(&results); err != nil { return err } sort.Sort(sort.Reverse(results)) w := tabwriter.NewWriter(cli.out, 10, 1, 3, ' ', 0) fmt.Fprintf(w, "NAME\tDESCRIPTION\tSTARS\tOFFICIAL\tAUTOMATED\n") for _, res := range results { if ((*automated || *trusted) && (!res.IsTrusted && !res.IsAutomated)) || (int(*stars) > res.StarCount) { continue } desc := strings.Replace(res.Description, "\n", " ", -1) desc = strings.Replace(desc, "\r", " ", -1) if !*noTrunc && len(desc) > 45 { desc = stringutils.Truncate(desc, 42) + "..." } fmt.Fprintf(w, "%s\t%s\t%d\t", res.Name, desc, res.StarCount) if res.IsOfficial { fmt.Fprint(w, "[OK]") } fmt.Fprint(w, "\t") if res.IsAutomated || res.IsTrusted { fmt.Fprint(w, "[OK]") } fmt.Fprint(w, "\n") } w.Flush() return nil }
// Create an image // POST /images // /docker_remote_api_v1.16/#create-an-image func (ic *ImagesController) Create(w http.ResponseWriter, r *http.Request) { params := r.URL.Query() endpoint := fmt.Sprintf("/images/create") q, err := NewRequest("POST", endpoint, params.Get("host")) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } auth := r.Header.Get("Authorization") if auth != "" { q.Set("X-Registry-Auth", auth) } var ( image = params.Get("fromImage") repo = params.Get("repo") tag = params.Get("tag") src = params.Get("fromSrc") options = createOptions{Registry: params.Get("registry")} ) if image != "" { // pull if tag == "" { image, tag = parsers.ParseRepositoryTag(image) } options.FromImage = image options.Tag = defaultTo(tag, DEFAULTTAG) } else { // import if tag == "" { repo, tag = parsers.ParseRepositoryTag(repo) } options.FromSrc = src options.Repo = repo options.Tag = defaultTo(tag, DEFAULTTAG) } q.Query(options) q.Timeout(0) b, err := q.Do() if !q.ValidateStatusCode(200, 500) && err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } w.WriteHeader(q.StatusCode) //w.Header().Set("Content-Type", "application/json;charset=utf-8") io.Copy(w, b) }
// parseImageName parses a docker image string into two parts: repo and tag. // If tag is empty, return the defaultImageTag. func parseImageName(image string) (string, string) { repoToPull, tag := parsers.ParseRepositoryTag(image) // If no tag was specified, use the default "latest". if len(tag) == 0 { tag = defaultImageTag } return repoToPull, tag }
// CmdImport creates an empty filesystem image, imports the contents of the tarball into the image, and optionally tags the image. // // The URL argument is the address of a tarball (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz) file or a path to local file relative to docker client. If the URL is '-', then the tar file is read from STDIN. // // Usage: docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]] func (cli *DockerCli) CmdImport(args ...string) error { cmd := Cli.Subcmd("import", []string{"file|URL|- [REPOSITORY[:TAG]]"}, Cli.DockerCommands["import"].Description, true) flChanges := opts.NewListOpts(nil) cmd.Var(&flChanges, []string{"c", "-change"}, "Apply Dockerfile instruction to the created image") message := cmd.String([]string{"m", "-message"}, "", "Set commit message for imported image") cmd.Require(flag.Min, 1) cmd.ParseFlags(args, true) var ( v = url.Values{} src = cmd.Arg(0) repository = cmd.Arg(1) ) v.Set("fromSrc", src) v.Set("repo", repository) v.Set("message", *message) for _, change := range flChanges.GetAll() { v.Add("changes", change) } if cmd.NArg() == 3 { fmt.Fprintf(cli.err, "[DEPRECATED] The format 'file|URL|- [REPOSITORY [TAG]]' has been deprecated. Please use file|URL|- [REPOSITORY[:TAG]]\n") v.Set("tag", cmd.Arg(2)) } if repository != "" { //Check if the given image name can be resolved repo, _ := parsers.ParseRepositoryTag(repository) if err := registry.ValidateRepositoryName(repo); err != nil { return err } } var in io.Reader if src == "-" { in = cli.in } else if !urlutil.IsURL(src) { v.Set("fromSrc", "-") file, err := os.Open(src) if err != nil { return err } defer file.Close() in = file } sopts := &streamOpts{ rawTerminal: true, in: in, out: cli.out, } _, err := cli.stream("POST", "/images/create?"+v.Encode(), sopts) return err }