// 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) remote, tag := parsers.ParseRepositoryTag(cmd.Arg(0)) // 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 }
// CmdCreate creates a new container from a given image. // // Usage: docker create [OPTIONS] IMAGE [COMMAND] [ARG...] func (cli *DockerCli) CmdCreate(args ...string) error { cmd := Cli.Subcmd("create", []string{"IMAGE [COMMAND] [ARG...]"}, "Create a new container", true) addTrustedFlags(cmd, true) // These are flags not stored in Config/HostConfig var ( flName = cmd.String([]string{"-name"}, "", "Assign a name to the container") ) config, hostConfig, cmd, err := runconfig.Parse(cmd, args) if err != nil { cmd.ReportError(err.Error(), true) os.Exit(1) } if config.Image == "" { cmd.Usage() return nil } response, err := cli.createContainer(config, hostConfig, hostConfig.ContainerIDFile, *flName) if err != nil { return err } fmt.Fprintf(cli.out, "%s\n", response.ID) return nil }
// CmdRm removes one or more containers. // // Usage: docker rm [OPTIONS] CONTAINER [CONTAINER...] func (cli *DockerCli) CmdRm(args ...string) error { cmd := Cli.Subcmd("rm", []string{"CONTAINER [CONTAINER...]"}, Cli.DockerCommands["rm"].Description, true) v := cmd.Bool([]string{"v", "-volumes"}, false, "Remove the volumes associated with the container") link := cmd.Bool([]string{"l", "-link"}, false, "Remove the specified link") force := cmd.Bool([]string{"f", "-force"}, false, "Force the removal of a running container (uses SIGKILL)") cmd.Require(flag.Min, 1) cmd.ParseFlags(args, true) var errs []string for _, name := range cmd.Args() { if name == "" { return fmt.Errorf("Container name cannot be empty") } name = strings.Trim(name, "/") if err := cli.removeContainer(name, *v, *link, *force); err != nil { errs = append(errs, err.Error()) } else { fmt.Fprintf(cli.out, "%s\n", name) } } if len(errs) > 0 { return fmt.Errorf("%s", strings.Join(errs, "\n")) } return nil }
// CmdDiff shows changes on a container's filesystem. // // Each changed file is printed on a separate line, prefixed with a single // character that indicates the status of the file: C (modified), A (added), // or D (deleted). // // Usage: docker diff CONTAINER func (cli *DockerCli) CmdDiff(args ...string) error { cmd := Cli.Subcmd("diff", []string{"CONTAINER"}, Cli.DockerCommands["diff"].Description, true) cmd.Require(flag.Exact, 1) cmd.ParseFlags(args, true) if cmd.Arg(0) == "" { return fmt.Errorf("Container name cannot be empty") } changes, err := cli.client.ContainerDiff(context.Background(), cmd.Arg(0)) if err != nil { return err } for _, change := range changes { var kind string switch change.Kind { case archive.ChangeModify: kind = "C" case archive.ChangeAdd: kind = "A" case archive.ChangeDelete: kind = "D" } fmt.Fprintf(cli.out, "%s %s\n", kind, change.Path) } return nil }
// CmdInspect displays low-level information on one or more containers, images or tasks. // // Usage: docker inspect [OPTIONS] CONTAINER|IMAGE|TASK [CONTAINER|IMAGE|TASK...] func (cli *DockerCli) CmdInspect(args ...string) error { cmd := Cli.Subcmd("inspect", []string{"CONTAINER|IMAGE|TASK [CONTAINER|IMAGE|TASK...]"}, Cli.DockerCommands["inspect"].Description, true) tmplStr := cmd.String([]string{"f", "-format"}, "", "Format the output using the given go template") inspectType := cmd.String([]string{"-type"}, "", "Return JSON for specified type, (e.g image, container or task)") size := cmd.Bool([]string{"s", "-size"}, false, "Display total file sizes if the type is container") cmd.Require(flag.Min, 1) cmd.ParseFlags(args, true) if *inspectType != "" && *inspectType != "container" && *inspectType != "image" && *inspectType != "task" { return fmt.Errorf("%q is not a valid value for --type", *inspectType) } ctx := context.Background() var elementSearcher inspect.GetRefFunc switch *inspectType { case "container": elementSearcher = cli.inspectContainers(ctx, *size) case "image": elementSearcher = cli.inspectImages(ctx, *size) case "task": if *size { fmt.Fprintln(cli.err, "WARNING: --size ignored for tasks") } elementSearcher = cli.inspectTasks(ctx) default: elementSearcher = cli.inspectAll(ctx, *size) } return inspect.Inspect(cli.out, cmd.Args(), *tmplStr, elementSearcher) }
// 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", []string{"NAME[:TAG|@DIGEST]"}, Cli.DockerCommands["pull"].Description, 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) remote := cmd.Arg(0) distributionRef, err := reference.ParseNamed(remote) if err != nil { return err } if *allTags && !reference.IsNameOnly(distributionRef) { return errors.New("tag can't be used with --all-tags/-a") } if !*allTags && reference.IsNameOnly(distributionRef) { distributionRef = reference.WithDefaultTag(distributionRef) fmt.Fprintf(cli.out, "Using default tag: %s\n", reference.DefaultTag) } // Resolve the Repository name from fqn to RepositoryInfo repoInfo, err := registry.ParseRepositoryInfo(distributionRef) if err != nil { return err } authConfig := cli.resolveAuthConfig(repoInfo.Index) requestPrivilege := cli.registryAuthenticationPrivilegedFunc(repoInfo.Index, "pull") return cli.imagePullPrivileged(authConfig, distributionRef.String(), "", requestPrivilege) }
// CmdLogout logs a user out from a Docker registry. // // If no server is specified, the user will be logged out from the registry's index server. // // Usage: docker logout [SERVER] func (cli *DockerCli) CmdLogout(args ...string) error { cmd := Cli.Subcmd("logout", []string{"[SERVER]"}, Cli.DockerCommands["logout"].Description+".\nIf no server is specified, the default is defined by the daemon.", true) cmd.Require(flag.Max, 1) cmd.ParseFlags(args, true) var serverAddress string if len(cmd.Args()) > 0 { serverAddress = cmd.Arg(0) } else { serverAddress = cli.electAuthServer() } // check if we're logged in based on the records in the config file // which means it couldn't have user/pass cause they may be in the creds store if _, ok := cli.configFile.AuthConfigs[serverAddress]; !ok { fmt.Fprintf(cli.out, "Not logged in to %s\n", serverAddress) return nil } fmt.Fprintf(cli.out, "Remove login credentials for %s\n", serverAddress) if err := eraseCredentials(cli.configFile, serverAddress); err != nil { fmt.Fprintf(cli.out, "WARNING: could not erase credentials: %v\n", err) } return 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]"}, Cli.DockerCommands["push"].Description, true) addTrustedFlags(cmd, false) cmd.Require(flag.Exact, 1) cmd.ParseFlags(args, true) ref, err := reference.ParseNamed(cmd.Arg(0)) if err != nil { return err } var tag string switch x := ref.(type) { case reference.Canonical: return errors.New("cannot push a digest reference") case reference.NamedTagged: tag = x.Tag() } // Resolve the Repository name from fqn to RepositoryInfo repoInfo, err := registry.ParseRepositoryInfo(ref) if err != nil { return err } // Resolve the Auth config relevant for this server authConfig := registry.ResolveAuthConfig(cli.configFile.AuthConfigs, repoInfo.Index) requestPrivilege := cli.registryAuthenticationPrivilegedFunc(repoInfo.Index, "push") if isTrusted() { return cli.trustedPush(repoInfo, tag, authConfig, requestPrivilege) } return cli.imagePushPrivileged(authConfig, ref.Name(), tag, cli.out, requestPrivilege) }
// CmdTop displays the running processes of a container. // // Usage: docker top CONTAINER func (cli *DockerCli) CmdTop(args ...string) error { cmd := Cli.Subcmd("top", []string{"CONTAINER [ps OPTIONS]"}, Cli.DockerCommands["top"].Description, true) cmd.Require(flag.Min, 1) cmd.ParseFlags(args, true) val := url.Values{} if cmd.NArg() > 1 { val.Set("ps_args", strings.Join(cmd.Args()[1:], " ")) } serverResp, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/top?"+val.Encode(), nil, nil) if err != nil { return err } defer serverResp.body.Close() procList := types.ContainerProcessList{} if err := json.NewDecoder(serverResp.body).Decode(&procList); err != nil { return err } w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0) fmt.Fprintln(w, strings.Join(procList.Titles, "\t")) for _, proc := range procList.Processes { fmt.Fprintln(w, strings.Join(proc, "\t")) } w.Flush() return nil }
// CmdStop stops one or more running containers. // // A running container is stopped by first sending SIGTERM and then SIGKILL if the container fails to stop within a grace period (the default is 10 seconds). // // Usage: docker stop [OPTIONS] CONTAINER [CONTAINER...] func (cli *DockerCli) CmdStop(args ...string) error { cmd := Cli.Subcmd("stop", []string{"CONTAINER [CONTAINER...]"}, "Stop a running container by sending SIGTERM and then SIGKILL after a\ngrace period", true) nSeconds := cmd.Int([]string{"t", "-time"}, 10, "Seconds to wait for stop before killing it") cmd.Require(flag.Min, 1) cmd.ParseFlags(args, true) v := url.Values{} v.Set("t", strconv.Itoa(*nSeconds)) var errNames []string for _, name := range cmd.Args() { _, _, err := readBody(cli.call("POST", "/containers/"+name+"/stop?"+v.Encode(), nil, nil)) if err != nil { fmt.Fprintf(cli.err, "%s\n", err) errNames = append(errNames, name) } else { fmt.Fprintf(cli.out, "%s\n", name) } } if len(errNames) > 0 { return fmt.Errorf("Error: failed to stop containers: %v", errNames) } return nil }
// CmdTop displays the running processes of a container. // // Usage: docker top CONTAINER func (cli *DockerCli) CmdTop(args ...string) error { cmd := Cli.Subcmd("top", []string{"CONTAINER [ps OPTIONS]"}, Cli.DockerCommands["top"].Description, true) cmd.Require(flag.Min, 1) cmd.ParseFlags(args, true) var arguments []string if cmd.NArg() > 1 { arguments = cmd.Args()[1:] } procList, err := cli.client.ContainerTop(context.Background(), cmd.Arg(0), arguments) if err != nil { return err } w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0) fmt.Fprintln(w, strings.Join(procList.Titles, "\t")) for _, proc := range procList.Processes { fmt.Fprintln(w, strings.Join(proc, "\t")) } w.Flush() return 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", []string{"IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG]"}, Cli.DockerCommands["tag"].Description, true) force := cmd.Bool([]string{"f", "-force"}, false, "Force") cmd.Require(flag.Exact, 2) cmd.ParseFlags(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 }
// CmdLoad loads an image from a tar archive. // // The tar archive is read from STDIN by default, or from a tar archive file. // // Usage: docker load [OPTIONS] func (cli *DockerCli) CmdLoad(args ...string) error { cmd := Cli.Subcmd("load", nil, Cli.DockerCommands["load"].Description, true) infile := cmd.String([]string{"i", "-input"}, "", "Read from a tar archive file, instead of STDIN") cmd.Require(flag.Exact, 0) cmd.ParseFlags(args, true) var input io.Reader = cli.in if *infile != "" { file, err := os.Open(*infile) if err != nil { return err } defer file.Close() input = file } responseBody, err := cli.client.ImageLoad(input) if err != nil { return err } defer responseBody.Close() _, err = io.Copy(cli.out, responseBody) return err }
// CmdRm removes one or more containers. // // Usage: docker rm [OPTIONS] CONTAINER [CONTAINER...] func (cli *DockerCli) CmdRm(args ...string) error { cmd := Cli.Subcmd("rm", []string{"CONTAINER [CONTAINER...]"}, Cli.DockerCommands["rm"].Description, true) v := cmd.Bool([]string{"v", "-volumes"}, false, "Remove the volumes associated with the container") link := cmd.Bool([]string{"l", "-link"}, false, "Remove the specified link") force := cmd.Bool([]string{"f", "-force"}, false, "Force the removal of a running container (uses SIGKILL)") cmd.Require(flag.Min, 1) cmd.ParseFlags(args, true) var errNames []string for _, name := range cmd.Args() { if name == "" { return fmt.Errorf("Container name cannot be empty") } name = strings.Trim(name, "/") options := types.ContainerRemoveOptions{ ContainerID: name, RemoveVolumes: *v, RemoveLinks: *link, Force: *force, } if err := cli.client.ContainerRemove(options); err != nil { fmt.Fprintf(cli.err, "%s\n", err) errNames = append(errNames, name) } else { fmt.Fprintf(cli.out, "%s\n", name) } } if len(errNames) > 0 { return fmt.Errorf("Error: failed to remove containers: %v", errNames) } return nil }
// CmdExport exports a filesystem as a tar archive. // // The tar archive is streamed to STDOUT by default or written to a file. // // Usage: docker export [OPTIONS] CONTAINER func (cli *DockerCli) CmdExport(args ...string) error { cmd := Cli.Subcmd("export", []string{"CONTAINER"}, Cli.DockerCommands["export"].Description, true) outfile := cmd.String([]string{"o", "-output"}, "", "Write to a file, instead of STDOUT") cmd.Require(flag.Exact, 1) cmd.ParseFlags(args, true) if *outfile == "" && cli.isTerminalOut { return errors.New("Cowardly refusing to save to a terminal. Use the -o flag or redirect.") } responseBody, err := cli.client.ContainerExport(context.Background(), cmd.Arg(0)) if err != nil { return err } defer responseBody.Close() if *outfile == "" { _, err := io.Copy(cli.out, responseBody) return err } return copyToFile(*outfile, responseBody) }
// CmdLoad loads an image from a tar archive. // // The tar archive is read from STDIN by default, or from a tar archive file. // // Usage: docker load [OPTIONS] func (cli *DockerCli) CmdLoad(args ...string) error { cmd := Cli.Subcmd("load", nil, Cli.DockerCommands["load"].Description, true) infile := cmd.String([]string{"i", "-input"}, "", "Read from a tar archive file, instead of STDIN") quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Suppress the load output") cmd.Require(flag.Exact, 0) cmd.ParseFlags(args, true) var input io.Reader = cli.in if *infile != "" { file, err := os.Open(*infile) if err != nil { return err } defer file.Close() input = file } if !cli.isTerminalOut { *quiet = true } response, err := cli.client.ImageLoad(context.Background(), input, *quiet) if err != nil { return err } defer response.Body.Close() if response.JSON { return jsonmessage.DisplayJSONMessagesStream(response.Body, cli.out, cli.outFd, cli.isTerminalOut, nil) } _, err = io.Copy(cli.out, response.Body) return err }
// 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 }
// CmdNetworkCreate creates a new network with a given name // // Usage: docker network create [OPTIONS] <NETWORK-NAME> func (cli *DockerCli) CmdNetworkCreate(args ...string) error { cmd := Cli.Subcmd("network create", []string{"NETWORK-NAME"}, "Creates a new network with a name specified by the user", false) flDriver := cmd.String([]string{"d", "-driver"}, "bridge", "Driver to manage the Network") flOpts := opts.NewMapOpts(nil, nil) flIpamDriver := cmd.String([]string{"-ipam-driver"}, "default", "IP Address Management Driver") flIpamSubnet := opts.NewListOpts(nil) flIpamIPRange := opts.NewListOpts(nil) flIpamGateway := opts.NewListOpts(nil) flIpamAux := opts.NewMapOpts(nil, nil) flIpamOpt := opts.NewMapOpts(nil, nil) flLabels := opts.NewListOpts(nil) cmd.Var(&flIpamSubnet, []string{"-subnet"}, "subnet in CIDR format that represents a network segment") cmd.Var(&flIpamIPRange, []string{"-ip-range"}, "allocate container ip from a sub-range") cmd.Var(&flIpamGateway, []string{"-gateway"}, "ipv4 or ipv6 Gateway for the master subnet") cmd.Var(flIpamAux, []string{"-aux-address"}, "auxiliary ipv4 or ipv6 addresses used by Network driver") cmd.Var(flOpts, []string{"o", "-opt"}, "set driver specific options") cmd.Var(flIpamOpt, []string{"-ipam-opt"}, "set IPAM driver specific options") cmd.Var(&flLabels, []string{"-label"}, "set metadata on a network") flInternal := cmd.Bool([]string{"-internal"}, false, "restricts external access to the network") flIPv6 := cmd.Bool([]string{"-ipv6"}, false, "enable IPv6 networking") cmd.Require(flag.Exact, 1) err := cmd.ParseFlags(args, true) if err != nil { return err } // Set the default driver to "" if the user didn't set the value. // That way we can know whether it was user input or not. driver := *flDriver if !cmd.IsSet("-driver") && !cmd.IsSet("d") { driver = "" } ipamCfg, err := consolidateIpam(flIpamSubnet.GetAll(), flIpamIPRange.GetAll(), flIpamGateway.GetAll(), flIpamAux.GetAll()) if err != nil { return err } // Construct network create request body nc := types.NetworkCreate{ Driver: driver, IPAM: network.IPAM{Driver: *flIpamDriver, Config: ipamCfg, Options: flIpamOpt.GetAll()}, Options: flOpts.GetAll(), CheckDuplicate: true, Internal: *flInternal, EnableIPv6: *flIPv6, Labels: runconfigopts.ConvertKVStringsToMap(flLabels.GetAll()), } resp, err := cli.client.NetworkCreate(context.Background(), cmd.Arg(0), nc) if err != nil { return err } fmt.Fprintf(cli.out, "%s\n", resp.ID) return 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", []string{"IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG]"}, Cli.DockerCommands["tag"].Description, true) force := cmd.Bool([]string{"#f", "#-force"}, false, "Force the tagging even if there's a conflict") cmd.Require(flag.Exact, 2) cmd.ParseFlags(args, true) ref, err := reference.ParseNamed(cmd.Arg(1)) if err != nil { return err } if _, isCanonical := ref.(reference.Canonical); isCanonical { return errors.New("refusing to create a tag with a digest reference") } var tag string if tagged, isTagged := ref.(reference.NamedTagged); isTagged { tag = tagged.Tag() } options := types.ImageTagOptions{ ImageID: cmd.Arg(0), RepositoryName: ref.Name(), Tag: tag, Force: *force, } return cli.client.ImageTag(context.Background(), options) }
// 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]"}, Cli.DockerCommands["push"].Description, true) addTrustedFlags(cmd, false) cmd.Require(flag.Exact, 1) cmd.ParseFlags(args, true) ref, err := reference.ParseNamed(cmd.Arg(0)) if err != nil { return err } // Resolve the Repository name from fqn to RepositoryInfo repoInfo, err := registry.ParseRepositoryInfo(ref) if err != nil { return err } // Resolve the Auth config relevant for this server authConfig := cli.resolveAuthConfig(repoInfo.Index) requestPrivilege := cli.registryAuthenticationPrivilegedFunc(repoInfo.Index, "push") if isTrusted() { return cli.trustedPush(repoInfo, ref, authConfig, requestPrivilege) } responseBody, err := cli.imagePushPrivileged(authConfig, ref.String(), requestPrivilege) if err != nil { return err } defer responseBody.Close() return jsonmessage.DisplayJSONMessagesStream(responseBody, cli.out, cli.outFd, cli.isTerminalOut, nil) }
// CmdInspect displays low-level information on one or more containers or images. // // Usage: docker inspect [OPTIONS] CONTAINER|IMAGE [CONTAINER|IMAGE...] func (cli *DockerCli) CmdInspect(args ...string) error { cmd := Cli.Subcmd("inspect", []string{"CONTAINER|IMAGE [CONTAINER|IMAGE...]"}, Cli.DockerCommands["inspect"].Description, true) tmplStr := cmd.String([]string{"f", "-format"}, "", "Format the output using the given go template") inspectType := cmd.String([]string{"-type"}, "", "Return JSON for specified type, (e.g image or container)") size := cmd.Bool([]string{"s", "-size"}, false, "Display total file sizes if the type is container") cmd.Require(flag.Min, 1) cmd.ParseFlags(args, true) if *inspectType != "" && *inspectType != "container" && *inspectType != "image" { return fmt.Errorf("%q is not a valid value for --type", *inspectType) } var elementSearcher inspectSearcher switch *inspectType { case "container": elementSearcher = cli.inspectContainers(*size) case "image": elementSearcher = cli.inspectImages(*size) default: elementSearcher = cli.inspectAll(*size) } return cli.inspectElements(*tmplStr, cmd.Args(), elementSearcher) }
// CmdVolumeCreate creates a new volume. // // Usage: docker volume create [OPTIONS] func (cli *DockerCli) CmdVolumeCreate(args ...string) error { cmd := Cli.Subcmd("volume create", nil, "Create a volume", true) flDriver := cmd.String([]string{"d", "-driver"}, "local", "Specify volume driver name") flName := cmd.String([]string{"-name"}, "", "Specify volume name") flDriverOpts := opts.NewMapOpts(nil, nil) cmd.Var(flDriverOpts, []string{"o", "-opt"}, "Set driver specific options") cmd.Require(flag.Exact, 0) cmd.ParseFlags(args, true) volReq := types.VolumeCreateRequest{ Driver: *flDriver, DriverOpts: flDriverOpts.GetAll(), Name: *flName, } vol, err := cli.client.VolumeCreate(context.Background(), volReq) if err != nil { return err } fmt.Fprintf(cli.out, "%s\n", vol.Name) return nil }
// CmdExport exports a filesystem as a tar archive. // // The tar archive is streamed to STDOUT by default or written to a file. // // Usage: docker export [OPTIONS] CONTAINER func (cli *DockerCli) CmdExport(args ...string) error { cmd := Cli.Subcmd("export", []string{"CONTAINER"}, "Export the contents of a container's filesystem as a tar archive", true) outfile := cmd.String([]string{"o", "-output"}, "", "Write to a file, instead of STDOUT") cmd.Require(flag.Exact, 1) cmd.ParseFlags(args, true) var ( output = cli.out err error ) if *outfile != "" { output, err = os.Create(*outfile) if err != nil { return err } } else if cli.isTerminalOut { return errors.New("Cowardly refusing to save to a terminal. Use the -o flag or redirect.") } image := cmd.Arg(0) sopts := &streamOpts{ rawTerminal: true, out: output, } if _, err := cli.stream("GET", "/containers/"+image+"/export", sopts); err != nil { return err } return nil }
// CmdNetworkInspect inspects the network object for more details // // Usage: docker network inspect <NETWORK> // CmdNetworkInspect handles Network inspect UI func (cli *DockerCli) CmdNetworkInspect(args ...string) error { cmd := Cli.Subcmd("network inspect", []string{"NETWORK"}, "Displays detailed information on a network", false) cmd.Require(flag.Exact, 1) err := cmd.ParseFlags(args, true) if err != nil { return err } obj, _, err := readBody(cli.call("GET", "/networks/"+cmd.Arg(0), nil, nil)) if err != nil { return err } networkResource := &types.NetworkResource{} if err := json.NewDecoder(bytes.NewReader(obj)).Decode(networkResource); err != nil { return err } indented := new(bytes.Buffer) if err := json.Indent(indented, obj, "", " "); err != nil { return err } if _, err := io.Copy(cli.out, indented); err != nil { return err } return nil }
// CmdNetwork is the parent subcommand for all network commands // // Usage: docker network <COMMAND> [OPTIONS] func (cli *DockerCli) CmdNetwork(args ...string) error { cmd := Cli.Subcmd("network", []string{"COMMAND [OPTIONS]"}, networkUsage(), false) cmd.Require(flag.Min, 1) err := cmd.ParseFlags(args, true) cmd.Usage() return err }
// CmdSave saves one or more images to a tar archive. // // The tar archive is written to STDOUT by default, or written to a file. // // Usage: docker save [OPTIONS] IMAGE [IMAGE...] func (cli *DockerCli) CmdSave(args ...string) error { cmd := Cli.Subcmd("save", []string{"IMAGE [IMAGE...]"}, Cli.DockerCommands["save"].Description+" (streamed to STDOUT by default)", true) outfile := cmd.String([]string{"o", "-output"}, "", "Write to a file, instead of STDOUT") cmd.Require(flag.Min, 1) cmd.ParseFlags(args, true) var ( output = cli.out err error ) if *outfile == "" && cli.isTerminalOut { return errors.New("Cowardly refusing to save to a terminal. Use the -o flag or redirect.") } if *outfile != "" { if output, err = os.Create(*outfile); err != nil { return err } } responseBody, err := cli.client.ImageSave(cmd.Args()) if err != nil { return err } defer responseBody.Close() _, err = io.Copy(output, responseBody) return err }
// CmdVolumeCreate creates a new container from a given image. // // Usage: docker volume create [OPTIONS] func (cli *DockerCli) CmdVolumeCreate(args ...string) error { cmd := Cli.Subcmd("volume create", nil, "Create a volume", true) flDriver := cmd.String([]string{"d", "-driver"}, "local", "Specify volume driver name") flName := cmd.String([]string{"-name"}, "", "Specify volume name") flDriverOpts := opts.NewMapOpts(nil, nil) cmd.Var(flDriverOpts, []string{"o", "-opt"}, "Set driver specific options") cmd.Require(flag.Exact, 0) cmd.ParseFlags(args, true) volReq := &types.VolumeCreateRequest{ Driver: *flDriver, DriverOpts: flDriverOpts.GetAll(), } if *flName != "" { volReq.Name = *flName } resp, err := cli.call("POST", "/volumes", volReq, nil) if err != nil { return err } var vol types.Volume if err := json.NewDecoder(resp.body).Decode(&vol); err != nil { return err } fmt.Fprintf(cli.out, "%s\n", vol.Name) return nil }
// CmdRestart restarts one or more containers. // // Usage: docker restart [OPTIONS] CONTAINER [CONTAINER...] func (cli *DockerCli) CmdRestart(args ...string) error { cmd := Cli.Subcmd("restart", []string{"CONTAINER [CONTAINER...]"}, "Restart a container", true) nSeconds := cmd.Int([]string{"t", "-time"}, 10, "Seconds to wait for stop before killing the container") cmd.Require(flag.Min, 1) cmd.ParseFlags(args, true) v := url.Values{} v.Set("t", strconv.Itoa(*nSeconds)) var errNames []string for _, name := range cmd.Args() { _, _, err := readBody(cli.call("POST", "/containers/"+name+"/restart?"+v.Encode(), nil, nil)) if err != nil { fmt.Fprintf(cli.err, "%s\n", err) errNames = append(errNames, name) } else { fmt.Fprintf(cli.out, "%s\n", name) } } if len(errNames) > 0 { return fmt.Errorf("Error: failed to restart containers: %v", errNames) } return nil }
// CmdLoad loads an image from a tar archive. // // The tar archive is read from STDIN by default, or from a tar archive file. // // Usage: docker load [OPTIONS] func (cli *DockerCli) CmdLoad(args ...string) error { cmd := Cli.Subcmd("load", nil, "Load an image from a tar archive or STDIN", true) infile := cmd.String([]string{"i", "-input"}, "", "Read from a tar archive file, instead of STDIN") cmd.Require(flag.Exact, 0) cmd.ParseFlags(args, true) var ( input io.Reader = cli.in err error ) if *infile != "" { input, err = os.Open(*infile) if err != nil { return err } } sopts := &streamOpts{ rawTerminal: true, in: input, out: cli.out, } if _, err := cli.stream("POST", "/images/load", sopts); err != nil { return err } return nil }
// CmdLogout logs a user out from a Docker registry. // // If no server is specified, the user will be logged out from the registry's index server. // // Usage: docker logout [SERVER] func (cli *DockerCli) CmdLogout(args ...string) error { cmd := Cli.Subcmd("logout", []string{"[SERVER]"}, Cli.DockerCommands["logout"].Description+".\nIf no server is specified, the default is defined by the daemon.", true) cmd.Require(flag.Max, 1) cmd.ParseFlags(args, true) var serverAddress string if len(cmd.Args()) > 0 { serverAddress = cmd.Arg(0) } else { serverAddress = cli.electAuthServer() } if _, ok := cli.configFile.AuthConfigs[serverAddress]; !ok { fmt.Fprintf(cli.out, "Not logged in to %s\n", serverAddress) return nil } fmt.Fprintf(cli.out, "Remove login credentials for %s\n", serverAddress) delete(cli.configFile.AuthConfigs, serverAddress) if err := cli.configFile.Save(); err != nil { return fmt.Errorf("Failed to save docker config: %v", err) } return nil }