// ImageList returns a list of images in the docker host. func (cli *Client) ImageList(options types.ImageListOptions) ([]types.Image, error) { var images []types.Image query := url.Values{} if options.Filters.Len() > 0 { filterJSON, err := filters.ToParam(options.Filters) if err != nil { return images, err } query.Set("filters", filterJSON) } if options.MatchName != "" { // FIXME rename this parameter, to not be confused with the filters flag query.Set("filter", options.MatchName) } if options.All { query.Set("all", "1") } serverResp, err := cli.get("/images/json", query, nil) if err != nil { return images, err } defer ensureReaderClosed(serverResp) err = json.NewDecoder(serverResp.body).Decode(&images) return images, err }
// Events returns a stream of events in the daemon in a ReadCloser. // It's up to the caller to close the stream. func (cli *Client) Events(options types.EventsOptions) (io.ReadCloser, error) { query := url.Values{} ref := time.Now() if options.Since != "" { ts, err := timeutils.GetTimestamp(options.Since, ref) if err != nil { return nil, err } query.Set("since", ts) } if options.Until != "" { ts, err := timeutils.GetTimestamp(options.Until, ref) if err != nil { return nil, err } query.Set("until", ts) } if options.Filters.Len() > 0 { filterJSON, err := filters.ToParam(options.Filters) if err != nil { return nil, err } query.Set("filters", filterJSON) } serverResponse, err := cli.get("/events", query, nil) if err != nil { return nil, err } return serverResponse.body, nil }
// CmdEvents prints a live stream of real time events from the server. // // Usage: docker events [OPTIONS] func (cli *DockerCli) CmdEvents(args ...string) error { cmd := cli.Subcmd("events", "", "Get real time events from the server", true) since := cmd.String([]string{"#since", "-since"}, "", "Show all events created since timestamp") until := cmd.String([]string{"-until"}, "", "Stream events until this timestamp") flFilter := opts.NewListOpts(nil) cmd.Var(&flFilter, []string{"f", "-filter"}, "Filter output based on conditions provided") cmd.Require(flag.Exact, 0) cmd.ParseFlags(args, true) var ( v = url.Values{} loc = time.FixedZone(time.Now().Zone()) eventFilterArgs = filters.Args{} ) // Consolidate all filter flags, and sanity check them early. // They'll get process in the daemon/server. for _, f := range flFilter.GetAll() { var err error eventFilterArgs, err = filters.ParseFlag(f, eventFilterArgs) if err != nil { return err } } var setTime = func(key, value string) { format := timeutils.RFC3339NanoFixed if len(value) < len(format) { format = format[:len(value)] } if t, err := time.ParseInLocation(format, value, loc); err == nil { v.Set(key, strconv.FormatInt(t.Unix(), 10)) } else { v.Set(key, value) } } if *since != "" { setTime("since", *since) } if *until != "" { setTime("until", *until) } if len(eventFilterArgs) > 0 { filterJSON, err := filters.ToParam(eventFilterArgs) if err != nil { return err } v.Set("filters", filterJSON) } sopts := &streamOpts{ rawTerminal: true, out: cli.out, } if err := cli.stream("GET", "/events?"+v.Encode(), sopts); err != nil { return err } return nil }
// CmdEvents prints a live stream of real time events from the server. // // Usage: docker events [OPTIONS] func (cli *DockerCli) CmdEvents(args ...string) error { cmd := Cli.Subcmd("events", nil, Cli.DockerCommands["events"].Description, true) since := cmd.String([]string{"-since"}, "", "Show all events created since timestamp") until := cmd.String([]string{"-until"}, "", "Stream events until this timestamp") flFilter := opts.NewListOpts(nil) cmd.Var(&flFilter, []string{"f", "-filter"}, "Filter output based on conditions provided") cmd.Require(flag.Exact, 0) cmd.ParseFlags(args, true) var ( v = url.Values{} eventFilterArgs = filters.NewArgs() ) // Consolidate all filter flags, and sanity check them early. // They'll get process in the daemon/server. for _, f := range flFilter.GetAll() { var err error eventFilterArgs, err = filters.ParseFlag(f, eventFilterArgs) if err != nil { return err } } ref := time.Now() if *since != "" { ts, err := timeutils.GetTimestamp(*since, ref) if err != nil { return err } v.Set("since", ts) } if *until != "" { ts, err := timeutils.GetTimestamp(*until, ref) if err != nil { return err } v.Set("until", ts) } if eventFilterArgs.Len() > 0 { filterJSON, err := filters.ToParam(eventFilterArgs) if err != nil { return err } v.Set("filters", filterJSON) } sopts := &streamOpts{ rawTerminal: true, out: cli.out, } if _, err := cli.stream("GET", "/events?"+v.Encode(), sopts); err != nil { return err } return nil }
// CmdVolumeLs outputs a list of Docker volumes. // // Usage: docker volume ls [OPTIONS] func (cli *DockerCli) CmdVolumeLs(args ...string) error { cmd := Cli.Subcmd("volume ls", nil, "List volumes", true) quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only display volume names") flFilter := opts.NewListOpts(nil) cmd.Var(&flFilter, []string{"f", "-filter"}, "Provide filter values (i.e. 'dangling=true')") cmd.Require(flag.Exact, 0) cmd.ParseFlags(args, true) volFilterArgs := filters.Args{} for _, f := range flFilter.GetAll() { var err error volFilterArgs, err = filters.ParseFlag(f, volFilterArgs) if err != nil { return err } } v := url.Values{} if len(volFilterArgs) > 0 { filterJSON, err := filters.ToParam(volFilterArgs) if err != nil { return err } v.Set("filters", filterJSON) } resp, err := cli.call("GET", "/volumes?"+v.Encode(), nil, nil) if err != nil { return err } var volumes types.VolumesListResponse if err := json.NewDecoder(resp.body).Decode(&volumes); err != nil { return err } w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0) if !*quiet { fmt.Fprintf(w, "DRIVER \tVOLUME NAME") fmt.Fprintf(w, "\n") } for _, vol := range volumes.Volumes { if *quiet { fmt.Fprintln(w, vol.Name) continue } fmt.Fprintf(w, "%s\t%s\n", vol.Driver, vol.Name) } w.Flush() return nil }
// ContainerList returns the list of containers in the docker host. func (cli *Client) ContainerList(options types.ContainerListOptions) ([]types.Container, error) { query := url.Values{} if options.All { query.Set("all", "1") } if options.Limit != -1 { query.Set("limit", strconv.Itoa(options.Limit)) } if options.Since != "" { query.Set("since", options.Since) } if options.Before != "" { query.Set("before", options.Before) } if options.Size { query.Set("size", "1") } if options.Filter.Len() > 0 { filterJSON, err := filters.ToParam(options.Filter) if err != nil { return nil, err } query.Set("filters", filterJSON) } resp, err := cli.get("/containers/json", query, nil) if err != nil { return nil, err } defer ensureReaderClosed(resp) var containers []types.Container err = json.NewDecoder(resp.body).Decode(&containers) return containers, err }
// VolumeList returns the volumes configured in the docker host. func (cli *Client) VolumeList(filter filters.Args) (types.VolumesListResponse, error) { var volumes types.VolumesListResponse query := url.Values{} if filter.Len() > 0 { filterJSON, err := filters.ToParam(filter) if err != nil { return volumes, err } query.Set("filters", filterJSON) } resp, err := cli.get("/volumes", query, nil) if err != nil { return volumes, err } defer ensureReaderClosed(resp) err = json.NewDecoder(resp.body).Decode(&volumes) return volumes, err }
func getNetworkIDByName(c *check.C, name string) string { var ( v = url.Values{} filterArgs = filters.NewArgs() ) filterArgs.Add("name", name) filterJSON, err := filters.ToParam(filterArgs) c.Assert(err, checker.IsNil) v.Set("filters", filterJSON) status, body, err := sockRequest("GET", "/networks?"+v.Encode(), nil) c.Assert(status, checker.Equals, http.StatusOK) c.Assert(err, checker.IsNil) nJSON := []types.NetworkResource{} err = json.Unmarshal(body, &nJSON) c.Assert(err, checker.IsNil) c.Assert(len(nJSON), checker.Equals, 1) return nJSON[0].ID }
// CmdImages lists the images in a specified repository, or all top-level images if no repository is specified. // // Usage: docker images [OPTIONS] [REPOSITORY] func (cli *DockerCli) CmdImages(args ...string) error { cmd := Cli.Subcmd("images", []string{"[REPOSITORY[:TAG]]"}, Cli.DockerCommands["images"].Description, true) quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only show numeric IDs") all := cmd.Bool([]string{"a", "-all"}, false, "Show all images (default hides intermediate images)") noTrunc := cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Don't truncate output") showDigests := cmd.Bool([]string{"-digests"}, false, "Show digests") flFilter := opts.NewListOpts(nil) cmd.Var(&flFilter, []string{"f", "-filter"}, "Filter output based on conditions provided") cmd.Require(flag.Max, 1) cmd.ParseFlags(args, true) // Consolidate all filter flags, and sanity check them early. // They'll get process in the daemon/server. imageFilterArgs := filters.Args{} for _, f := range flFilter.GetAll() { var err error imageFilterArgs, err = filters.ParseFlag(f, imageFilterArgs) if err != nil { return err } } matchName := cmd.Arg(0) v := url.Values{} if len(imageFilterArgs) > 0 { filterJSON, err := filters.ToParam(imageFilterArgs) if err != nil { return err } v.Set("filters", filterJSON) } if cmd.NArg() == 1 { // FIXME rename this parameter, to not be confused with the filters flag v.Set("filter", matchName) } if *all { v.Set("all", "1") } serverResp, err := cli.call("GET", "/images/json?"+v.Encode(), nil, nil) if err != nil { return err } defer serverResp.body.Close() images := []types.Image{} if err := json.NewDecoder(serverResp.body).Decode(&images); err != nil { return err } w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0) if !*quiet { if *showDigests { fmt.Fprintln(w, "REPOSITORY\tTAG\tDIGEST\tIMAGE ID\tCREATED\tVIRTUAL SIZE") } else { fmt.Fprintln(w, "REPOSITORY\tTAG\tIMAGE ID\tCREATED\tVIRTUAL SIZE") } } for _, image := range images { ID := image.ID if !*noTrunc { ID = stringid.TruncateID(ID) } repoTags := image.RepoTags repoDigests := image.RepoDigests if len(repoTags) == 1 && repoTags[0] == "<none>:<none>" && len(repoDigests) == 1 && repoDigests[0] == "<none>@<none>" { // dangling image - clear out either repoTags or repoDigsts so we only show it once below repoDigests = []string{} } // combine the tags and digests lists tagsAndDigests := append(repoTags, repoDigests...) for _, repoAndRef := range tagsAndDigests { repo, ref := parsers.ParseRepositoryTag(repoAndRef) // default tag and digest to none - if there's a value, it'll be set below tag := "<none>" digest := "<none>" if utils.DigestReference(ref) { digest = ref } else { tag = ref } if !*quiet { if *showDigests { fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s ago\t%s\n", repo, tag, digest, ID, units.HumanDuration(time.Now().UTC().Sub(time.Unix(int64(image.Created), 0))), units.HumanSize(float64(image.VirtualSize))) } else { fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\n", repo, tag, ID, units.HumanDuration(time.Now().UTC().Sub(time.Unix(int64(image.Created), 0))), units.HumanSize(float64(image.VirtualSize))) } } else { fmt.Fprintln(w, ID) } } } if !*quiet { 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 }
// 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") format = cmd.String([]string{"-format"}, "", "Pretty-print containers using a Go template") 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 } f := *format if len(f) == 0 { if len(cli.PsFormat()) > 0 && !*quiet { f = cli.PsFormat() } else { f = "table" } } psCtx := ps.Context{ Output: cli.out, Format: f, Quiet: *quiet, Size: *size, Trunc: !*noTrunc, } ps.Format(psCtx, containers) return nil }
// CmdImages lists the images in a specified repository, or all top-level images if no repository is specified. // // Usage: docker images [OPTIONS] [REPOSITORY] func (cli *DockerCli) CmdImages(args ...string) error { cmd := cli.Subcmd("images", "[REPOSITORY]", "List images", true) quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only show numeric IDs") all := cmd.Bool([]string{"a", "-all"}, false, "Show all images (default hides intermediate images)") noTrunc := cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Don't truncate output") showDigests := cmd.Bool([]string{"-digests"}, false, "Show digests") // FIXME: --viz and --tree are deprecated. Remove them in a future version. flViz := cmd.Bool([]string{"#v", "#viz", "#-viz"}, false, "Output graph in graphviz format") flTree := cmd.Bool([]string{"#t", "#tree", "#-tree"}, false, "Output graph in tree format") flFilter := opts.NewListOpts(nil) cmd.Var(&flFilter, []string{"f", "-filter"}, "Filter output based on conditions provided") cmd.Require(flag.Max, 1) utils.ParseFlags(cmd, args, true) // Consolidate all filter flags, and sanity check them early. // They'll get process in the daemon/server. imageFilterArgs := filters.Args{} for _, f := range flFilter.GetAll() { var err error imageFilterArgs, err = filters.ParseFlag(f, imageFilterArgs) if err != nil { return err } } matchName := cmd.Arg(0) // FIXME: --viz and --tree are deprecated. Remove them in a future version. if *flViz || *flTree { v := url.Values{ "all": []string{"1"}, } if len(imageFilterArgs) > 0 { filterJSON, err := filters.ToParam(imageFilterArgs) if err != nil { return err } v.Set("filters", filterJSON) } body, _, err := readBody(cli.call("GET", "/images/json?"+v.Encode(), nil, nil)) if err != nil { return err } outs := engine.NewTable("Created", 0) if _, err := outs.ReadListFrom(body); err != nil { return err } var ( printNode func(cli *DockerCli, noTrunc bool, image *engine.Env, prefix string) startImage *engine.Env roots = engine.NewTable("Created", outs.Len()) byParent = make(map[string]*engine.Table) ) for _, image := range outs.Data { if image.Get("ParentId") == "" { roots.Add(image) } else { if children, exists := byParent[image.Get("ParentId")]; exists { children.Add(image) } else { byParent[image.Get("ParentId")] = engine.NewTable("Created", 1) byParent[image.Get("ParentId")].Add(image) } } if matchName != "" { if matchName == image.Get("Id") || matchName == stringid.TruncateID(image.Get("Id")) { startImage = image } for _, repotag := range image.GetList("RepoTags") { if repotag == matchName { startImage = image } } } } if *flViz { fmt.Fprintf(cli.out, "digraph docker {\n") printNode = (*DockerCli).printVizNode } else { printNode = (*DockerCli).printTreeNode } if startImage != nil { root := engine.NewTable("Created", 1) root.Add(startImage) cli.WalkTree(*noTrunc, root, byParent, "", printNode) } else if matchName == "" { cli.WalkTree(*noTrunc, roots, byParent, "", printNode) } if *flViz { fmt.Fprintf(cli.out, " base [style=invisible]\n}\n") } } else { v := url.Values{} if len(imageFilterArgs) > 0 { filterJSON, err := filters.ToParam(imageFilterArgs) if err != nil { return err } v.Set("filters", filterJSON) } if cmd.NArg() == 1 { // FIXME rename this parameter, to not be confused with the filters flag v.Set("filter", matchName) } if *all { v.Set("all", "1") } body, _, err := readBody(cli.call("GET", "/images/json?"+v.Encode(), nil, nil)) if err != nil { return err } outs := engine.NewTable("Created", 0) if _, err := outs.ReadListFrom(body); err != nil { return err } w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0) if !*quiet { if *showDigests { fmt.Fprintln(w, "REPOSITORY\tTAG\tDIGEST\tIMAGE ID\tCREATED\tVIRTUAL SIZE") } else { fmt.Fprintln(w, "REPOSITORY\tTAG\tIMAGE ID\tCREATED\tVIRTUAL SIZE") } } for _, out := range outs.Data { outID := out.Get("Id") if !*noTrunc { outID = stringid.TruncateID(outID) } repoTags := out.GetList("RepoTags") repoDigests := out.GetList("RepoDigests") if len(repoTags) == 1 && repoTags[0] == "<none>:<none>" && len(repoDigests) == 1 && repoDigests[0] == "<none>@<none>" { // dangling image - clear out either repoTags or repoDigsts so we only show it once below repoDigests = []string{} } // combine the tags and digests lists tagsAndDigests := append(repoTags, repoDigests...) for _, repoAndRef := range tagsAndDigests { repo, ref := parsers.ParseRepositoryTag(repoAndRef) // default tag and digest to none - if there's a value, it'll be set below tag := "<none>" digest := "<none>" if utils.DigestReference(ref) { digest = ref } else { tag = ref } if !*quiet { if *showDigests { fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s ago\t%s\n", repo, tag, digest, outID, units.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))), units.HumanSize(float64(out.GetInt64("VirtualSize")))) } else { fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\n", repo, tag, outID, units.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))), units.HumanSize(float64(out.GetInt64("VirtualSize")))) } } else { fmt.Fprintln(w, outID) } } } if !*quiet { w.Flush() } } return nil }