// 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 }
func (c *containerContext) Command() string { c.addHeader(commandHeader) command := c.c.Command if c.trunc { command = stringutils.Truncate(command, 20) } return strconv.Quote(command) }
// CmdHistory shows the history of an image. // // Usage: docker history [OPTIONS] IMAGE func (cli *DockerCli) CmdHistory(args ...string) error { cmd := Cli.Subcmd("history", []string{"IMAGE"}, Cli.DockerCommands["history"].Description, true) human := cmd.Bool([]string{"H", "-human"}, true, "Print sizes and dates in human readable format") quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only show numeric IDs") noTrunc := cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Don't truncate output") cmd.Require(flag.Exact, 1) cmd.ParseFlags(args, true) serverResp, err := cli.call("GET", "/images/"+cmd.Arg(0)+"/history", nil, nil) if err != nil { return err } defer serverResp.body.Close() history := []types.ImageHistory{} if err := json.NewDecoder(serverResp.body).Decode(&history); err != nil { return err } w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0) if !*quiet { fmt.Fprintln(w, "IMAGE\tCREATED\tCREATED BY\tSIZE\tCOMMENT") } for _, entry := range history { if *noTrunc { fmt.Fprintf(w, entry.ID) } else { fmt.Fprintf(w, stringid.TruncateID(entry.ID)) } if !*quiet { if *human { fmt.Fprintf(w, "\t%s ago\t", units.HumanDuration(time.Now().UTC().Sub(time.Unix(entry.Created, 0)))) } else { fmt.Fprintf(w, "\t%s\t", time.Unix(entry.Created, 0).Format(time.RFC3339)) } if *noTrunc { fmt.Fprintf(w, "%s\t", strings.Replace(entry.CreatedBy, "\t", " ", -1)) } else { fmt.Fprintf(w, "%s\t", stringutils.Truncate(strings.Replace(entry.CreatedBy, "\t", " ", -1), 45)) } if *human { fmt.Fprintf(w, "%s\t", units.HumanSize(float64(entry.Size))) } else { fmt.Fprintf(w, "%d\t", entry.Size) } fmt.Fprintf(w, "%s", entry.Comment) } fmt.Fprintf(w, "\n") } w.Flush() return nil }
func (c *containerContext) Image() string { c.addHeader(imageHeader) if c.c.Image == "" { return "<no image>" } if c.trunc { return stringutils.Truncate(c.c.Image, 12) } return c.c.Image }
// CmdHistory shows the history of an image. // // Usage: docker history [OPTIONS] IMAGE func (cli *DockerCli) CmdHistory(args ...string) error { cmd := Cli.Subcmd("history", []string{"IMAGE"}, Cli.DockerCommands["history"].Description, true) human := cmd.Bool([]string{"H", "-human"}, true, "Print sizes and dates in human readable format") quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only show numeric IDs") noTrunc := cmd.Bool([]string{"-no-trunc"}, false, "Don't truncate output") cmd.Require(flag.Exact, 1) cmd.ParseFlags(args, true) history, err := cli.client.ImageHistory(cmd.Arg(0)) if err != nil { return err } w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0) if *quiet { for _, entry := range history { if *noTrunc { fmt.Fprintf(w, "%s\n", entry.ID) } else { fmt.Fprintf(w, "%s\n", stringid.TruncateID(entry.ID)) } } w.Flush() return nil } var imageID string var createdBy string var created string var size string fmt.Fprintln(w, "IMAGE\tCREATED\tCREATED BY\tSIZE\tCOMMENT") for _, entry := range history { imageID = entry.ID createdBy = strings.Replace(entry.CreatedBy, "\t", " ", -1) if *noTrunc == false { createdBy = stringutils.Truncate(createdBy, 45) imageID = stringid.TruncateID(entry.ID) } if *human { created = units.HumanDuration(time.Now().UTC().Sub(time.Unix(entry.Created, 0))) + " ago" size = units.HumanSize(float64(entry.Size)) } else { created = time.Unix(entry.Created, 0).Format(time.RFC3339) size = strconv.FormatInt(entry.Size, 10) } fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", imageID, created, createdBy, size, entry.Comment) } w.Flush() return nil }
func (c *containerContext) Mounts() string { c.addHeader(mountsHeader) var mounts []string for _, m := range c.c.Mounts { name := m.Name if c.trunc { name = stringutils.Truncate(name, 15) } mounts = append(mounts, name) } return strings.Join(mounts, ",") }
func runHistory(dockerCli *client.DockerCli, opts historyOptions) error { ctx := context.Background() history, err := dockerCli.Client().ImageHistory(ctx, opts.image) if err != nil { return err } w := tabwriter.NewWriter(dockerCli.Out(), 20, 1, 3, ' ', 0) if opts.quiet { for _, entry := range history { if opts.noTrunc { fmt.Fprintf(w, "%s\n", entry.ID) } else { fmt.Fprintf(w, "%s\n", stringid.TruncateID(entry.ID)) } } w.Flush() return nil } var imageID string var createdBy string var created string var size string fmt.Fprintln(w, "IMAGE\tCREATED\tCREATED BY\tSIZE\tCOMMENT") for _, entry := range history { imageID = entry.ID createdBy = strings.Replace(entry.CreatedBy, "\t", " ", -1) if opts.noTrunc == false { createdBy = stringutils.Truncate(createdBy, 45) imageID = stringid.TruncateID(entry.ID) } if opts.human { created = units.HumanDuration(time.Now().UTC().Sub(time.Unix(entry.Created, 0))) + " ago" size = units.HumanSize(float64(entry.Size)) } else { created = time.Unix(entry.Created, 0).Format(time.RFC3339) size = strconv.FormatInt(entry.Size, 10) } fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", imageID, created, createdBy, size, entry.Comment) } w.Flush() return nil }
// CmdHistory shows the history of an image. // // Usage: docker history [OPTIONS] IMAGE func (cli *DockerCli) CmdHistory(args ...string) error { cmd := cli.Subcmd("history", "IMAGE", "Show the history of an image", true) quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only show numeric IDs") noTrunc := cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Don't truncate output") cmd.Require(flag.Exact, 1) cmd.ParseFlags(args, true) rdr, _, err := cli.call("GET", "/images/"+cmd.Arg(0)+"/history", nil, nil) if err != nil { return err } history := []types.ImageHistory{} err = json.NewDecoder(rdr).Decode(&history) if err != nil { return err } w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0) if !*quiet { fmt.Fprintln(w, "IMAGE\tCREATED\tCREATED BY\tSIZE\tCOMMENT") } for _, entry := range history { if *noTrunc { fmt.Fprintf(w, entry.ID) } else { fmt.Fprintf(w, stringid.TruncateID(entry.ID)) } if !*quiet { fmt.Fprintf(w, "\t%s ago\t", units.HumanDuration(time.Now().UTC().Sub(time.Unix(entry.Created, 0)))) if *noTrunc { fmt.Fprintf(w, "%s\t", entry.CreatedBy) } else { fmt.Fprintf(w, "%s\t", stringutils.Truncate(entry.CreatedBy, 45)) } fmt.Fprintf(w, "%s\t", units.HumanSize(float64(entry.Size))) fmt.Fprintf(w, "%s", entry.Comment) } fmt.Fprintf(w, "\n") } w.Flush() return 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"}, Cli.DockerCommands["search"].Description, true) noTrunc := cmd.Bool([]string{"-no-trunc"}, false, "Don't truncate output") automated := cmd.Bool([]string{"-automated"}, false, "Only show automated builds") stars := cmd.Uint([]string{"s", "-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) indexInfo, err := registry.ParseSearchIndexInfo(name) if err != nil { return err } authConfig := registry.ResolveAuthConfig(cli.configFile.AuthConfigs, indexInfo) requestPrivilege := cli.registryAuthenticationPrivilegedFunc(indexInfo, "search") encodedAuth, err := encodeAuthToBase64(authConfig) if err != nil { return err } options := types.ImageSearchOptions{ Term: name, RegistryAuth: encodedAuth, } unorderedResults, err := cli.client.ImageSearch(options, requestPrivilege) if err != nil { return err } results := searchResultsByStars(unorderedResults) sort.Sort(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 && !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 }
// CmdPs outputs a list of Docker containers. // // Usage: docker ps [OPTIONS] func (cli *DockerCli) CmdPs(args ...string) error { var ( err error psFilterArgs = filters.Args{} v = url.Values{} cmd = cli.Subcmd("ps", nil, "List containers", true) quiet = cmd.Bool([]string{"q", "-quiet"}, false, "Only display numeric IDs") size = cmd.Bool([]string{"s", "-size"}, false, "Display total file sizes") all = cmd.Bool([]string{"a", "-all"}, false, "Show all containers (default shows just running)") noTrunc = cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Don't truncate output") nLatest = cmd.Bool([]string{"l", "-latest"}, false, "Show the latest created container, include non-running") since = cmd.String([]string{"#sinceId", "#-since-id", "-since"}, "", "Show created since Id or Name, include non-running") before = cmd.String([]string{"#beforeId", "#-before-id", "-before"}, "", "Show only container created before Id or Name") last = cmd.Int([]string{"n"}, -1, "Show n last created containers, include non-running") flFilter = opts.NewListOpts(nil) ) cmd.Require(flag.Exact, 0) cmd.Var(&flFilter, []string{"f", "-filter"}, "Filter output based on conditions provided") cmd.ParseFlags(args, true) if *last == -1 && *nLatest { *last = 1 } if *all { v.Set("all", "1") } if *last != -1 { v.Set("limit", strconv.Itoa(*last)) } if *since != "" { v.Set("since", *since) } if *before != "" { v.Set("before", *before) } if *size { v.Set("size", "1") } // Consolidate all filter flags, and sanity check them. // They'll get processed in the daemon/server. for _, f := range flFilter.GetAll() { if psFilterArgs, err = filters.ParseFlag(f, psFilterArgs); err != nil { return err } } if len(psFilterArgs) > 0 { filterJSON, err := filters.ToParam(psFilterArgs) if err != nil { return err } v.Set("filters", filterJSON) } serverResp, err := cli.call("GET", "/containers/json?"+v.Encode(), nil, nil) if err != nil { return err } defer serverResp.body.Close() containers := []types.Container{} if err := json.NewDecoder(serverResp.body).Decode(&containers); err != nil { return err } w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0) if !*quiet { fmt.Fprint(w, "CONTAINER ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tPORTS\tNAMES") if *size { fmt.Fprintln(w, "\tSIZE") } else { fmt.Fprint(w, "\n") } } stripNamePrefix := func(ss []string) []string { for i, s := range ss { ss[i] = s[1:] } return ss } for _, container := range containers { ID := container.ID if !*noTrunc { ID = stringid.TruncateID(ID) } if *quiet { fmt.Fprintln(w, ID) continue } var ( names = stripNamePrefix(container.Names) command = strconv.Quote(container.Command) displayPort string ) if !*noTrunc { command = stringutils.Truncate(command, 20) // only display the default name for the container with notrunc is passed for _, name := range names { if len(strings.Split(name, "/")) == 1 { names = []string{name} break } } } image := container.Image if image == "" { image = "<no image>" } if container.HostConfig.NetworkMode == "host" { displayPort = "*/tcp, */udp" } else { displayPort = api.DisplayablePorts(container.Ports) } fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\t%s\t%s\t", ID, image, command, units.HumanDuration(time.Now().UTC().Sub(time.Unix(int64(container.Created), 0))), container.Status, displayPort, strings.Join(names, ",")) if *size { if container.SizeRootFs > 0 { fmt.Fprintf(w, "%s (virtual %s)\n", units.HumanSize(float64(container.SizeRw)), units.HumanSize(float64(container.SizeRootFs))) } else { fmt.Fprintf(w, "%s\n", units.HumanSize(float64(container.SizeRw))) } continue } fmt.Fprint(w, "\n") } if !*quiet { w.Flush() } return nil }
func runSearch(dockerCli *client.DockerCli, opts searchOptions) error { indexInfo, err := registry.ParseSearchIndexInfo(opts.term) if err != nil { return err } ctx := context.Background() authConfig := dockerCli.ResolveAuthConfig(ctx, indexInfo) requestPrivilege := dockerCli.RegistryAuthenticationPrivilegedFunc(indexInfo, "search") encodedAuth, err := client.EncodeAuthToBase64(authConfig) if err != nil { return err } searchFilters := filters.NewArgs() for _, f := range opts.filter { var err error searchFilters, err = filters.ParseFlag(f, searchFilters) if err != nil { return err } } options := types.ImageSearchOptions{ RegistryAuth: encodedAuth, PrivilegeFunc: requestPrivilege, Filters: searchFilters, Limit: opts.limit, } clnt := dockerCli.Client() unorderedResults, err := clnt.ImageSearch(ctx, opts.term, options) if err != nil { return err } results := searchResultsByStars(unorderedResults) sort.Sort(results) w := tabwriter.NewWriter(dockerCli.Out(), 10, 1, 3, ' ', 0) fmt.Fprintf(w, "NAME\tDESCRIPTION\tSTARS\tOFFICIAL\tAUTOMATED\n") for _, res := range results { // --automated and -s, --stars are deprecated since Docker 1.12 if (opts.automated && !res.IsAutomated) || (int(opts.stars) > res.StarCount) { continue } desc := strings.Replace(res.Description, "\n", " ", -1) desc = strings.Replace(desc, "\r", " ", -1) if !opts.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 { fmt.Fprint(w, "[OK]") } fmt.Fprint(w, "\n") } w.Flush() return nil }
// CmdSearch searches the Docker Hub for images. // // Usage: docker search [OPTIONS] TERM func (cli *DockerCli) CmdSearch(args ...string) error { var ( err error filterArgs = filters.NewArgs() flFilter = opts.NewListOpts(nil) ) cmd := Cli.Subcmd("search", []string{"TERM"}, Cli.DockerCommands["search"].Description, true) noTrunc := cmd.Bool([]string{"-no-trunc"}, false, "Don't truncate output") cmd.Var(&flFilter, []string{"f", "-filter"}, "Filter output based on conditions provided") // Deprecated since Docker 1.12 in favor of "--filter" automated := cmd.Bool([]string{"#-automated"}, false, "Only show automated builds - DEPRECATED") stars := cmd.Uint([]string{"s", "#-stars"}, 0, "Only displays with at least x stars - DEPRECATED") cmd.Require(flag.Exact, 1) cmd.ParseFlags(args, true) for _, f := range flFilter.GetAll() { if filterArgs, err = filters.ParseFlag(f, filterArgs); err != nil { return err } } name := cmd.Arg(0) v := url.Values{} v.Set("term", name) indexInfo, err := registry.ParseSearchIndexInfo(name) if err != nil { return err } ctx := context.Background() authConfig := cli.resolveAuthConfig(ctx, indexInfo) requestPrivilege := cli.registryAuthenticationPrivilegedFunc(indexInfo, "search") encodedAuth, err := encodeAuthToBase64(authConfig) if err != nil { return err } options := types.ImageSearchOptions{ RegistryAuth: encodedAuth, PrivilegeFunc: requestPrivilege, Filters: filterArgs, } unorderedResults, err := cli.client.ImageSearch(ctx, name, options) if err != nil { return err } results := searchResultsByStars(unorderedResults) sort.Sort(results) w := tabwriter.NewWriter(cli.out, 10, 1, 3, ' ', 0) fmt.Fprintf(w, "NAME\tDESCRIPTION\tSTARS\tOFFICIAL\tAUTOMATED\n") for _, res := range results { // --automated and -s, --stars are deprecated since Docker 1.12 if (*automated && !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 { fmt.Fprint(w, "[OK]") } fmt.Fprint(w, "\n") } w.Flush() return nil }