func pullImageInSilence(ctx *cobra.Command, name string) error { r, n, t, err := client.ParseRepositoryName(name) if err != nil { return err } name = n + ":" + t if r != "" { name = r + "/" + name } f, err := os.Open(os.DevNull) if err != nil { return err } docker, err := client.NewDockerClient(configPath, hostName, f) if err != nil { return err } if _, err := docker.PullImage(name); err != nil { return err } return nil }
func inspectContainers(ctx *cobra.Command, args []string) { if len(args) < 1 { ErrorExit(ctx, "Needs an argument <NAME|ID> at least to inspect") } docker, err := client.NewDockerClient(configPath, hostName, ctx.Out()) if err != nil { log.Fatal(err) } var containers []api.ContainerInfo var gotError = false for _, name := range args { if containerInfo, err := docker.InspectContainer(name); err != nil { log.Error(err) gotError = true } else { containers = append(containers, *containerInfo) } } if len(containers) > 0 { if err := FormatPrint(ctx.Out(), containers); err != nil { log.Fatal(err) } } if gotError { log.Fatal("Error: failed to inspect one or more containers") } }
func getContainerChanges(ctx *cobra.Command, args []string) { if len(args) < 1 { ErrorExit(ctx, "Needs an argument <NAME|ID> to get changes") } docker, err := client.NewDockerClient(configPath, hostName, ctx.Out()) if err != nil { log.Fatal(err) } changes, err := docker.GetContainerChanges(args[0]) if err != nil { log.Fatal(err) } for _, change := range changes { var kind string switch change.Kind { case api.CHANGE_TYPE_MODIFY: kind = "C" case api.CHANGE_TYPE_ADD: kind = "A" case api.CHANGE_TYPE_DELETE: kind = "D" } ctx.Printf("%s %s\n", kind, change.Path) } }
func inspectImages(ctx *cobra.Command, args []string) { if len(args) < 1 { ErrorExit(ctx, "Needs an argument <NAME[:TAG]|ID> at least to inspect") } docker, err := client.NewDockerClient(configPath, hostName, ctx.Out()) if err != nil { log.Fatal(err) } var images []api.ImageInfo var gotError = false for _, name := range args { if imageInfo, err := docker.InspectImage(name); err != nil { log.Error(err) gotError = true } else { images = append(images, *imageInfo) } } if len(images) > 0 { if err := FormatPrint(ctx.Out(), images); err != nil { log.Fatal(err) } } if gotError { log.Fatal("Error: failed to inspect one or more images") } }
func getContainerProcesses(ctx *cobra.Command, args []string) { if len(args) < 1 { ErrorExit(ctx, "Needs an argument <NAME|ID> to execute ps") } docker, err := client.NewDockerClient(configPath, hostName, ctx.Out()) if err != nil { log.Fatal(err) } ps_args := "" if len(args) > 1 { ps_args = strings.Join(args[1:], " ") } ps, err := docker.GetContainerProcesses(args[0], ps_args) if err != nil { log.Fatal(err) } if boolYAML || boolJSON { if err := FormatPrint(ctx.Out(), ps); err != nil { log.Fatal(err) } return } PrintInTable(ctx.Out(), ps.Titles, ps.Processes, 100, tablewriter.ALIGN_DEFAULT) }
func commitContainer(ctx *cobra.Command, args []string) { if len(args) < 2 { ErrorExit(ctx, "Needs two arguments to commit <CONTAINER-NAME|ID> to <IMAGE-NAME[:TAG]>") } reg, name, tag, err := client.ParseRepositoryName(args[1]) if err != nil { log.Fatal(err) } if reg != "" { name = reg + "/" + name } docker, err := client.NewDockerClient(configPath, hostName, ctx.Out()) if err != nil { log.Fatal(err) } if _, err := docker.CommitContainer(args[0], name, tag, message, author, boolPause); err != nil { log.Fatal(err) } ctx.Printf("Committed %s as %s:%s\n", args[0], name, tag) }
func tagImage(ctx *cobra.Command, args []string) { if len(args) < 2 { ErrorExit(ctx, "Needs two arguments <NAME[:TAG]|ID> <NEW-NAME[:TAG]>") } reg, name, tag, err := client.ParseRepositoryName(args[1]) if err != nil { log.Fatal(err) } if reg != "" { name = reg + "/" + name } docker, err := client.NewDockerClient(configPath, hostName, ctx.Out()) if err != nil { log.Fatal(err) } if err := docker.TagImage(args[0], name, tag, boolForce); err != nil { log.Fatal(err) } ctx.Printf("Tagged %s as %s:%s\n", args[0], name, tag) }
func pullImage(ctx *cobra.Command, args []string) { if len(args) < 1 { ErrorExit(ctx, "Needs an argument <NAME[:TAG]> to pull") } reg, name, tag, err := client.ParseRepositoryName(args[0]) if err != nil { log.Fatal(err) } repository := name + ":" + tag if boolAll { repository = name } if reg != "" { repository = reg + "/" + repository } docker, err := client.NewDockerClient(configPath, hostName, ctx.Out()) if err != nil { log.Fatal(err) } if _, err := docker.PullImage(repository); err != nil { log.Fatal(err) } }
func searchImages(ctx *cobra.Command, args []string) { if len(args) < 1 { ErrorExit(ctx, "Needs an argument <TERM> to search") } docker, err := client.NewDockerClient(configPath, hostName, ctx.Out()) if err != nil { log.Fatal(err) } images, err := docker.SearchImages(args[0]) if err != nil { log.Fatal(err) } if boolStar { sort.Sort(sort.Reverse(api.SortImagesByStars{ImageSearchResults: images})) } else { sort.Sort(api.SortImagesByName{ImageSearchResults: images}) } if boolQuiet { for _, image := range images { ctx.Println(image.Name) } return } if boolYAML || boolJSON { if err := FormatPrint(ctx.Out(), images); err != nil { log.Fatal(err) } return } var items [][]string for _, image := range images { out := []string{ image.Name, image.Description, FormatInt(int64(image.Stars)), FormatBool(image.Official, "*", " "), FormatBool(image.Automated, "*", " "), } items = append(items, out) } header := []string{ "Name", "Description", "Stars", "Official", "Automated", } PrintInTable(ctx.Out(), header, items, 50, tablewriter.ALIGN_DEFAULT) }
func exportVolume(ctx *cobra.Command, args []string) { if len(args) < 1 { ErrorExit(ctx, "Needs an argument <ID|CONTAINER-NAME:PATH> to export") } volumes, err := getVolumes(ctx) if err != nil { log.Fatal(err) } volume := volumes.Find(args[0]) if volume == nil { log.Fatalf("No such volume: %s", args[0]) } var ( config api.Config hostConfig api.HostConfig ) config.Image = "busybox:latest" hostConfig.Binds = []string{volume.Path + ":/" + volume.ID} docker, err := client.NewDockerClient(configPath, hostName, ctx.Out()) if err != nil { log.Fatal(err) } var cid string cid, err = docker.CreateContainer("", config, hostConfig) if err != nil { if apiErr, ok := err.(api.Error); ok && (apiErr.StatusCode == 404) { if err := pullImageInSilence(ctx, config.Image); err != nil { log.Fatal(err) } cid, err = docker.CreateContainer("", config, hostConfig) if err != nil { log.Fatal(err) } } else { log.Fatal(err) } } defer docker.RemoveContainer(cid, true) if err := docker.CopyContainer(cid, "/"+volume.ID); err != nil { log.Fatal(err) } }
func removeVolume(ctx *cobra.Command, volume *Volume) error { var ( config api.Config hostConfig api.HostConfig ) config.Cmd = []string{"/bin/sh", "-c", "rm -rf /.docker_volume_config/" + volume.ID} config.Image = "busybox:latest" hostConfig.Binds = []string{filepath.Dir(volume.configPath) + ":/.docker_volume_config"} if !volume.IsBindMount { config.Cmd[2] = config.Cmd[2] + (" && rm -rf /.docker_volume/" + volume.ID) hostConfig.Binds = append(hostConfig.Binds, filepath.Dir(volume.Path)+":/.docker_volume") } docker, err := client.NewDockerClient(configPath, hostName, ctx.Out()) if err != nil { return err } var cid string cid, err = docker.CreateContainer("", config, hostConfig) if err != nil { if apiErr, ok := err.(api.Error); ok && (apiErr.StatusCode == 404) { if err := pullImageInSilence(ctx, config.Image); err != nil { return err } cid, err = docker.CreateContainer("", config, hostConfig) if err != nil { return err } } else { return err } } defer docker.RemoveContainer(cid, true) if err := docker.StartContainer(cid); err != nil { return err } if _, err := docker.WaitContainer(cid); err != nil { return err } return nil }
func buildImage(ctx *cobra.Command, args []string) { path := "." if len(args) > 0 { path = args[0] } docker, err := client.NewDockerClient(configPath, hostName, ctx.Out()) if err != nil { log.Fatal(err) } if _, err := docker.BuildImage(path, imageTag, boolQuiet); err != nil { log.Fatal(err) } }
func exportContainer(ctx *cobra.Command, args []string) { if len(args) < 1 { ErrorExit(ctx, "Needs an argument <NAME|ID> to export") } docker, err := client.NewDockerClient(configPath, hostName, ctx.Out()) if err != nil { log.Fatal(err) } if len(args) > 1 { if err := docker.CopyContainer(args[0], args[1]); err != nil { log.Fatal(err) } } else { if err := docker.ExportContainer(args[0]); err != nil { log.Fatal(err) } } }
func pushImage(ctx *cobra.Command, args []string) { if len(args) < 1 { ErrorExit(ctx, "Needs an argument <NAME[:TAG]> to push") } reg, name, tag, err := client.ParseRepositoryName(args[0]) if err != nil { log.Fatal(err) } if len(strings.SplitN(name, "/", 2)) == 1 { log.Fatalf("You cannot push a \"root\" repository. Please rename your repository in <yourname>/%s", name) } if reg != "" { name = reg + "/" + name } config, err := client.LoadConfig(configPath) if err != nil { log.Fatal(err) } if reg == "" { reg = client.INDEX_SERVER } registry, err := config.GetRegistry(reg) if (err != nil) || (registry.Credentials == "") { log.Fatal("Please login prior to pushing an image.") } docker, err := client.NewDockerClient(configPath, hostName, ctx.Out()) if err != nil { log.Fatal(err) } if _, err := docker.PushImage(name, tag, registry.Credentials); err != nil { log.Fatal(err) } }
func removeImages(ctx *cobra.Command, args []string) { if len(args) < 1 { ErrorExit(ctx, "Needs an argument <NAME[:TAG]> at least to remove") } docker, err := client.NewDockerClient(configPath, hostName, ctx.Out()) if err != nil { log.Fatal(err) } var gotError = false for _, name := range args { if err := docker.RemoveImage(name, boolForce, boolNoPrune); err != nil { log.Error(err) gotError = true } } if gotError { log.Fatal("Error: failed to remove one or more images") } }
func getContainerLogs(ctx *cobra.Command, args []string) { if len(args) < 1 { ErrorExit(ctx, "Needs an argument <NAME|ID> to get logs") } docker, err := client.NewDockerClient(configPath, hostName, ctx.Out()) if err != nil { log.Fatal(err) } logs, err := docker.GetContainerLogs(args[0], false, true, true, boolTimestamps, tail) if err != nil { log.Fatal(err) } if logs[0] != "" { fmt.Fprint(os.Stdout, logs[0]) } if logs[1] != "" { fmt.Fprint(os.Stderr, logs[1]) } }
func waitContainers(ctx *cobra.Command, args []string) { if len(args) < 1 { ErrorExit(ctx, "Needs an argument <NAME|ID> at least to wait") } docker, err := client.NewDockerClient(configPath, hostName, ctx.Out()) if err != nil { log.Fatal(err) } var gotError = false for _, name := range args { if status, err := docker.WaitContainer(name); err != nil { log.Error(err) gotError = true } else { fmt.Fprintf(ctx.Out(), "%s: %d\n", name, status) } } if gotError { log.Fatal("Error: failed to wait one or more containers") } }
func removeContainers(ctx *cobra.Command, args []string) { if len(args) < 1 { ErrorExit(ctx, "Needs an argument <NAME|ID> at least to remove") } docker, err := client.NewDockerClient(configPath, hostName, ctx.Out()) if err != nil { log.Fatal(err) } var gotError = false for _, name := range args { if err := docker.RemoveContainer(name, boolForce); err != nil { log.Error(err) gotError = true } else { ctx.Println(name) } } if gotError { log.Fatal("Error: failed to remove one or more containers") } }
func composeContainer(ctx *cobra.Command, root string, composer Composer) (string, error) { var ( config api.Config hostConfig api.HostConfig localVolumes = make(map[string]struct{}) bindVolumes []string exposedPorts = make(map[string]struct{}) portBindings = make(map[string][]api.PortBinding) links []string deviceMappings []api.DeviceMapping ) if composer.Image != "" { r, n, t, err := client.ParseRepositoryName(composer.Image) if err != nil { return "", err } composer.Image = n + ":" + t if r != "" { composer.Image = r + "/" + composer.Image } } if (composer.WorkingDir != "") && !filepath.IsAbs(composer.WorkingDir) { return "", fmt.Errorf("Invalid working directory: it must be absolute.") } docker, err := client.NewDockerClient(configPath, hostName, ctx.Out()) if err != nil { return "", err } if composer.Build != "" { if !filepath.IsAbs(composer.Build) { composer.Build = filepath.Join(root, composer.Build) } message, err := docker.BuildImage(composer.Build, composer.Image, false) if err != nil { return "", err } if composer.Image == "" { if _, err := fmt.Sscanf(message, "Successfully built %s", &composer.Image); err != nil { return "", err } } } for _, port := range composer.Ports { var ( rawPort = port hostIp = "" hostPort = "" containerPort = "" proto = "tcp" ) if i := strings.LastIndex(port, "/"); i != -1 { proto = strings.ToLower(port[i+1:]) port = port[:i] } parts := strings.Split(port, ":") switch len(parts) { case 1: containerPort = parts[0] case 2: hostPort = parts[0] containerPort = parts[1] case 3: hostIp = parts[0] hostPort = parts[1] containerPort = parts[2] default: return "", fmt.Errorf("Invalid port specification: %s", rawPort) } port := fmt.Sprintf("%s/%s", containerPort, proto) if _, exists := exposedPorts[port]; !exists { exposedPorts[port] = struct{}{} } portBinding := api.PortBinding{ HostIp: hostIp, HostPort: hostPort, } bslice, exists := portBindings[port] if !exists { bslice = []api.PortBinding{} } portBindings[port] = append(bslice, portBinding) } for _, port := range composer.ExposedPorts { var ( rawPort = port containerPort = "" proto = "tcp" ) parts := strings.Split(containerPort, "/") switch len(parts) { case 1: containerPort = parts[0] case 2: containerPort = parts[0] proto = strings.ToLower(parts[1]) default: return "", fmt.Errorf("Invalid port specification: %s", rawPort) } port := fmt.Sprintf("%s/%s", containerPort, proto) if _, exists := exposedPorts[port]; !exists { exposedPorts[port] = struct{}{} } } for _, volume := range composer.Volumes { if arr := strings.Split(volume, ":"); len(arr) > 1 { if arr[1] == "/" { return "", fmt.Errorf("Invalid bind mount: destination can't be '/'") } if !filepath.IsAbs(arr[0]) { return "", fmt.Errorf("Invalid bind mount: the host path must be absolute.") } bindVolumes = append(bindVolumes, volume) } else if volume == "/" { return "", fmt.Errorf("Invalid volume: path can't be '/'") } else { localVolumes[volume] = struct{}{} } } for _, link := range append(composer.Links, composer.ExternalLinks...) { arr := strings.Split(link, ":") if len(arr) < 2 { links = append(links, arr[0]+":"+arr[0]) } else { links = append(links, link) } } for _, device := range composer.Devices { src := "" dst := "" permissions := "rwm" arr := strings.Split(device, ":") switch len(arr) { case 3: permissions = arr[2] fallthrough case 2: dst = arr[1] fallthrough case 1: src = arr[0] default: return "", fmt.Errorf("Invalid device specification: %s", device) } if dst == "" { dst = src } deviceMapping := api.DeviceMapping{ PathOnHost: src, PathInContainer: dst, CgroupPermissions: permissions, } deviceMappings = append(deviceMappings, deviceMapping) } parts := strings.Split(composer.RestartPolicy, ":") restartPolicy := api.RestartPolicy{} restartPolicy.Name = parts[0] if (restartPolicy.Name == "on-failure") && (len(parts) == 2) { count, err := strconv.Atoi(parts[1]) if err != nil { return "", err } restartPolicy.MaximumRetryCount = count } config.Hostname = composer.Hostname config.Domainname = composer.Domainname config.User = composer.User config.Memory = composer.Memory config.MemorySwap = composer.MemorySwap config.CpuShares = composer.CpuShares config.Cpuset = composer.Cpuset config.ExposedPorts = exposedPorts config.Tty = composer.Tty config.OpenStdin = composer.OpenStdin config.Env = composer.Env config.Cmd = composer.Cmd config.Image = composer.Image config.Volumes = localVolumes config.WorkingDir = composer.WorkingDir if composer.Entrypoint != "" { config.Entrypoint = []string{composer.Entrypoint} } config.MacAddress = composer.MacAddress hostConfig.Binds = bindVolumes hostConfig.Privileged = composer.Privileged hostConfig.PortBindings = portBindings hostConfig.Links = links hostConfig.PublishAllPorts = composer.PublishAllPorts hostConfig.Dns = composer.Dns hostConfig.DnsSearch = composer.DnsSearch hostConfig.ExtraHosts = composer.ExtraHosts hostConfig.VolumesFrom = composer.VolumesFrom hostConfig.Devices = deviceMappings hostConfig.NetworkMode = composer.NetworkMode hostConfig.IpcMode = composer.IpcMode hostConfig.PidMode = composer.PidMode hostConfig.CapAdd = composer.CapAdd hostConfig.CapDrop = composer.CapDrop hostConfig.RestartPolicy = restartPolicy hostConfig.SecurityOpt = composer.SecurityOpt hostConfig.ReadonlyRootfs = composer.ReadonlyRootfs var cid string cid, err = docker.CreateContainer(composer.Name, config, hostConfig) if err != nil { if apiErr, ok := err.(api.Error); ok && (apiErr.StatusCode == 404) { if _, err := docker.PullImage(config.Image); err != nil { return "", err } cid, err = docker.CreateContainer(composer.Name, config, hostConfig) if err != nil { return "", err } } else { return "", err } } return cid, nil }
func showImageHistory(ctx *cobra.Command, args []string) { if len(args) < 1 { ErrorExit(ctx, "Needs an argument <NAME[:TAG]|ID>") } docker, err := client.NewDockerClient(configPath, hostName, ctx.Out()) if err != nil { log.Fatal(err) } history, err := docker.GetImageHistory(args[0]) if err != nil { log.Fatal(err) } // Just reverse history var images api.ImageHistories for i, l := 0, len(history); i < l; i++ { images = append(images, history[l-i-1]) } if boolYAML || boolJSON { if err := FormatPrint(ctx.Out(), images); err != nil { log.Fatal(err) } return } var items [][]string for _, image := range images { re := regexp.MustCompile("\\s+") createdBy := re.ReplaceAllLiteralString(image.CreatedBy, " ") re = regexp.MustCompile("^/bin/sh -c #\\(nop\\) ") createdBy = re.ReplaceAllLiteralString(createdBy, "") re = regexp.MustCompile("^/bin/sh -c") createdBy = re.ReplaceAllLiteralString(createdBy, "RUN") tags := strings.Join(image.Tags, ", ") if !boolAll { createdBy = FormatNonBreakingString(Truncate(createdBy, 50)) tags = FormatNonBreakingString(tags) } out := []string{ Truncate(image.Id, 12), createdBy, tags, FormatDateTime(time.Unix(image.Created, 0)), FormatFloat(float64(image.Size) / 1000000), } items = append(items, out) } header := []string{ "ID", "Created by", "Name:Tags", "Created at", "Size(MB)", } PrintInTable(ctx.Out(), header, items, 20, tablewriter.ALIGN_DEFAULT) }
func listContainers(ctx *cobra.Command, args []string) { docker, err := client.NewDockerClient(configPath, hostName, ctx.Out()) if err != nil { log.Fatal(err) } limit := 0 if boolLatest { limit = 1 } containers, err := docker.ListContainers(boolAll, boolSize, limit, "", "", nil) if err != nil { log.Fatal(err) } if boolQuiet { for _, container := range containers { ctx.Println(Truncate(container.Id, 12)) } return } if boolYAML || boolJSON { if err := FormatPrint(ctx.Out(), containers); err != nil { log.Fatal(err) } return } trimNamePrefix := func(ss []string) []string { for i, s := range ss { ss[i] = strings.TrimPrefix(s, "/") } return ss } formatPorts := func(ports []api.Port) string { result := []string{} for _, p := range ports { if p.IP == "" { result = append(result, fmt.Sprintf("%d/%s", p.PrivatePort, p.Type)) } else { result = append(result, fmt.Sprintf("%s:%d->%d/%s", p.IP, p.PublicPort, p.PrivatePort, p.Type)) } } return strings.Join(result, ", ") } var items [][]string for _, container := range containers { out := []string{ Truncate(container.Id, 12), strings.Join(trimNamePrefix(container.Names), ", "), container.Image, Truncate(container.Command, 30), FormatDateTime(time.Unix(container.Created, 0)), container.Status, formatPorts(container.Ports), } if boolSize { out = append(out, FormatFloat(float64(container.SizeRw)/1000000)) } items = append(items, out) } header := []string{ "ID", "Names", "Image", "Command", "Created at", "Status", "Ports", } if boolSize { header = append(header, "Size(MB)") } PrintInTable(ctx.Out(), header, items, 0, tablewriter.ALIGN_DEFAULT) }
func getVolumes(ctx *cobra.Command) (Volumes, error) { docker, err := client.NewDockerClient(configPath, hostName, ctx.Out()) if err != nil { return nil, err } info, err := docker.Info() if err != nil { return nil, err } rootDir := "/var/lib/docker" if info.DockerRootDir != "" { rootDir = info.DockerRootDir } else { for _, pair := range info.DriverStatus { if pair[0] == "Root Dir" { rootDir = filepath.Dir(pair[1]) } } } path := filepath.Join(rootDir, "/volumes") var ( config api.Config hostConfig api.HostConfig ) config.Cmd = []string{"/bin/sh", "-c", "awk '{cmd=\"ls -e \" FILENAME; cmd | getline line; close(cmd); split(line,a,\" \"); print $0,a[6],a[7],a[8],a[9],a[10]}' /.docker_volumes/*/config.json"} config.Image = "busybox:latest" hostConfig.Binds = []string{path + ":/.docker_volumes:ro"} var cid string cid, err = docker.CreateContainer("", config, hostConfig) if err != nil { if apiErr, ok := err.(api.Error); ok && (apiErr.StatusCode == 404) { if err := pullImageInSilence(ctx, config.Image); err != nil { return nil, err } cid, err = docker.CreateContainer("", config, hostConfig) if err != nil { return nil, err } } else { return nil, err } } defer docker.RemoveContainer(cid, true) if err := docker.StartContainer(cid); err != nil { return nil, err } if _, err := docker.WaitContainer(cid); err != nil { return nil, err } logs, err := docker.GetContainerLogs(cid, false, true, true, false, 0) if err != nil { return nil, err } if logs[0] == "" { return nil, nil } vols := strings.Split(strings.TrimSpace(logs[0]), "\n") var volumes Volumes for _, vol := range vols { arr := strings.SplitN(vol, "} ", 2) volume := &Volume{} if err := json.Unmarshal([]byte(arr[0]+"}"), volume); err != nil { log.Debugf("%s: '%s'", err, arr[0]) return nil, err } volume.Created, _ = time.Parse(time.ANSIC, arr[1]) volume.configPath = filepath.Join(path, "/"+volume.ID) volumes = append(volumes, volume) } if err := docker.RemoveContainer(cid, true); err != nil { return nil, err } mounts, err := getMounts(ctx) if err != nil { return nil, err } for _, volume := range volumes { for _, mount := range mounts { if mount.hostPath == volume.Path { volume.MountedOn = append(volume.MountedOn, mount) } } } return volumes, nil }
func uploadToContainer(ctx *cobra.Command, args []string) { if len(args) < 2 { ErrorExit(ctx, "Needs two arguments <PATH> to upload into <(NAME|ID):PATH>") } srcPath, err := filepath.Abs(args[0]) if err != nil { log.Fatal(err) } arr := strings.Split(args[1], ":") if len(arr) < 2 || (arr[1] == "") { ErrorExit(ctx, fmt.Sprint("Needs <(NAME|ID):PATH> for the second argument")) } var ( name = arr[0] path = arr[1] ) f, err := os.Open(os.DevNull) if err != nil { log.Fatal(err) } docker, err := client.NewDockerClient(configPath, hostName, f) if err != nil { log.Fatal(err) } info, err := docker.Info() if err != nil { log.Fatal(err) } rootDir := "" for _, pair := range info.DriverStatus { if pair[0] == "Root Dir" { rootDir = pair[1] } } if rootDir == "" { if info.DockerRootDir == "" { log.Fatal("Can't get the root dir for the container") } rootDir = filepath.Join(info.DockerRootDir, info.Driver) } containerInfo, err := docker.InspectContainer(name) if err != nil { log.Fatal(err) } switch info.Driver { case "aufs": rootDir = filepath.Join(rootDir, "mnt", containerInfo.Id) case "btrfs": rootDir = filepath.Join(rootDir, "subvolumes", containerInfo.Id) case "devicemapper": rootDir = filepath.Join(rootDir, "mnt", containerInfo.Id, "rootfs") case "overlay": rootDir = filepath.Join(rootDir, containerInfo.Id, "merged") case "vfs": rootDir = filepath.Join(rootDir, "dir", containerInfo.Id) default: log.Fatalf("Unknown driver: %s", info.Driver) } dstPath := filepath.Join(rootDir, path) dstPath = filepath.Clean(dstPath) if !strings.HasPrefix(dstPath, rootDir) { log.Fatal("Can't upload to outside of the container") } ctx.Printf("Uploading %s into %s\n", args[0], args[1]) message, err := docker.Upload(srcPath, true) if err != nil { log.Fatal(err) } var ( config api.Config hostConfig api.HostConfig ) if _, err := fmt.Sscanf(message, "Successfully built %s", &config.Image); err != nil { log.Fatal(err) } defer docker.RemoveImage(config.Image, true, false) hostConfig.Binds = []string{dstPath + ":/.destination"} cid, err := docker.CreateContainer("", config, hostConfig) if err != nil { log.Fatal(err) } defer docker.RemoveContainer(cid, true) if err := docker.StartContainer(cid); err != nil { log.Fatal(err) } if _, err := docker.WaitContainer(cid); err != nil { log.Fatal(err) } ctx.Print("Successfully uploaded\n") }
func uploadToVolume(ctx *cobra.Command, args []string) { if len(args) < 2 { ErrorExit(ctx, "Needs two arguments <PATH> to upload into <ID:PATH>") } srcPath, err := filepath.Abs(args[0]) if err != nil { log.Fatal(err) } arr := strings.Split(args[1], ":") if len(arr) < 2 || (arr[1] == "") { ErrorExit(ctx, fmt.Sprint("Needs <ID:PATH> for the second argument")) } var ( id = arr[0] path = arr[1] ) volumes, err := getVolumes(ctx) if err != nil { log.Fatal(err) } volume := volumes.Find(id) if volume == nil { log.Fatalf("No such volume: %s", id) } dstPath := filepath.Join(volume.Path, path) dstPath = filepath.Clean(dstPath) if !strings.HasPrefix(dstPath, volume.Path) { log.Fatal("Can't upload to outside of the volume") } f, err := os.Open(os.DevNull) if err != nil { log.Fatal(err) } docker, err := client.NewDockerClient(configPath, hostName, f) if err != nil { log.Fatal(err) } ctx.Printf("Uploading %s into %s\n", args[0], args[1]) message, err := docker.Upload(srcPath, true) if err != nil { log.Fatal(err) } var ( config api.Config hostConfig api.HostConfig ) if _, err := fmt.Sscanf(message, "Successfully built %s", &config.Image); err != nil { log.Fatal(err) } defer docker.RemoveImage(config.Image, true, false) hostConfig.Binds = []string{dstPath + ":/.destination"} cid, err := docker.CreateContainer("", config, hostConfig) if err != nil { log.Fatal(err) } defer docker.RemoveContainer(cid, true) if err := docker.StartContainer(cid); err != nil { log.Fatal(err) } if _, err := docker.WaitContainer(cid); err != nil { log.Fatal(err) } ctx.Print("Successfully uploaded\n") }
func listImages(ctx *cobra.Command, args []string) { docker, err := client.NewDockerClient(configPath, hostName, ctx.Out()) if err != nil { log.Fatal(err) } images, err := docker.ListImages(boolAll, nil) if err != nil { log.Fatal(err) } matchName := "" if len(args) > 0 { matchName = args[0] } matchImageByName := func(tags []string, name string) bool { arrName := strings.Split(name, ":") for _, tag := range tags { arrTag := strings.Split(tag, ":") if arrTag[0] == arrName[0] { if (len(arrName) < 2) || (arrTag[1] == arrName[1]) { return true } } } return false } if boolQuiet { for _, image := range images { if (matchName == "") || matchImageByName(image.RepoTags, matchName) { ctx.Println(Truncate(image.Id, 12)) } } return } if boolYAML || boolJSON { items := []api.Image{} for _, image := range images { if (matchName == "") || matchImageByName(image.RepoTags, matchName) { items = append(items, image) } } if err := FormatPrint(ctx.Out(), items); err != nil { log.Fatal(err) } return } var items [][]string if boolAll { roots := []api.Image{} parents := map[string][]api.Image{} for _, image := range images { if image.ParentId == "" { roots = append(roots, image) } else { if children, exists := parents[image.ParentId]; exists { parents[image.ParentId] = append(children, image) } else { children := []api.Image{} parents[image.ParentId] = append(children, image) } } } items = walkTree(roots, parents, "", items) } else { for _, image := range images { if (matchName == "") || matchImageByName(image.RepoTags, matchName) { name := strings.Join(image.RepoTags, ", ") if name == "<none>:<none>" { name = "<none>" } out := []string{ Truncate(image.Id, 12), FormatNonBreakingString(name), FormatFloat(float64(image.VirtualSize) / 1000000), FormatDateTime(time.Unix(image.Created, 0)), } items = append(items, out) } } } header := []string{ "ID", "Name:Tags", "Size(MB)", } if !boolAll { header = append(header, "Created at") } PrintInTable(ctx.Out(), header, items, 0, tablewriter.ALIGN_DEFAULT) }
func getHostInfo(ctx *cobra.Command, args []string) { if len(args) > 0 { hostName = args[0] } config, err := client.LoadConfig(configPath) if err != nil { log.Fatal(err) } host, err := config.GetHost(hostName) if err != nil { log.Fatal(err) } docker, err := client.NewDockerClient(configPath, hostName, ctx.Out()) if err != nil { log.Fatal(err) } info, err := docker.Info() if err != nil { log.Fatal(err) } if boolYAML || boolJSON { data := make([]interface{}, 2) data[0] = host data[1] = info if err := FormatPrint(ctx.Out(), data); err != nil { log.Fatal(err) } return } var items [][]string items = append(items, []string{ "Host", host.Name, }) items = append(items, []string{ "URL", host.URL, }) items = append(items, []string{ "Description", FormatNonBreakingString(host.Description), }) items = append(items, []string{ "TLS", FormatBool(host.TLS, "Supported", "No"), }) if host.TLS { items = append(items, []string{ FormatNonBreakingString(" CA Certificate file"), FormatNonBreakingString(host.TLSCaCert), }) items = append(items, []string{ FormatNonBreakingString(" Certificate file"), FormatNonBreakingString(host.TLSCert), }) items = append(items, []string{ FormatNonBreakingString(" Key file"), FormatNonBreakingString(host.TLSKey), }) items = append(items, []string{ FormatNonBreakingString(" Verify"), FormatBool(host.TLSVerify, "Required", "No"), }) } items = append(items, []string{ "Containers", strconv.Itoa(info.Containers), }) items = append(items, []string{ "Images", strconv.Itoa(info.Images), }) items = append(items, []string{ "Storage Driver", info.Driver, }) for _, pair := range info.DriverStatus { items = append(items, []string{ FormatNonBreakingString(fmt.Sprintf(" %s", pair[0])), FormatNonBreakingString(fmt.Sprintf("%s", pair[1])), }) } items = append(items, []string{ "Execution Driver", info.ExecutionDriver, }) items = append(items, []string{ "Kernel Version", info.KernelVersion, }) items = append(items, []string{ "Operating System", FormatNonBreakingString(info.OperatingSystem), }) items = append(items, []string{ "CPUs", strconv.Itoa(info.NCPU), }) items = append(items, []string{ "Total Memory", fmt.Sprintf("%s GB", FormatFloat(float64(info.MemTotal)/1000000000)), }) items = append(items, []string{ "Index Server Address", info.IndexServerAddress, }) items = append(items, []string{ "Memory Limit", FormatBool((info.MemoryLimit != 0) && (info.MemoryLimit != false), "Supported", "No"), }) items = append(items, []string{ "Swap Limit", FormatBool((info.SwapLimit != 0) && (info.SwapLimit != false), "Supported", "No"), }) items = append(items, []string{ "IPv4 Forwarding", FormatBool((info.IPv4Forwarding != 0) && (info.IPv4Forwarding != false), "Enabled", "Disabled"), }) items = append(items, []string{ "ID", info.ID, }) items = append(items, []string{ "Name", info.Name, }) items = append(items, []string{ "Labels", FormatNonBreakingString(strings.Join(info.Labels, ", ")), }) items = append(items, []string{ "Debug Mode", FormatBool((info.Debug != 0) && (info.Debug != false), "Yes", "No"), }) if (info.Debug != 0) && (info.Debug != false) { items = append(items, []string{ FormatNonBreakingString(" Events Listeners"), strconv.Itoa(info.NEventsListener), }) items = append(items, []string{ FormatNonBreakingString(" Fds"), strconv.Itoa(info.NFd), }) items = append(items, []string{ FormatNonBreakingString(" Goroutines"), strconv.Itoa(info.NGoroutines), }) items = append(items, []string{ FormatNonBreakingString(" Init Path"), info.InitPath, }) items = append(items, []string{ FormatNonBreakingString(" Init SHA1"), info.InitSha1, }) items = append(items, []string{ FormatNonBreakingString(" Docker Root Dir"), info.DockerRootDir, }) } PrintInTable(ctx.Out(), nil, items, 0, tablewriter.ALIGN_LEFT) }
func getMounts(ctx *cobra.Command) ([]*Mount, error) { docker, err := client.NewDockerClient(configPath, hostName, ctx.Out()) if err != nil { return nil, err } containers, err := docker.ListContainers(true, false, 0, "", "", nil) if err != nil { return nil, err } var mounts []*Mount for _, container := range containers { localMounts := map[string]*Mount{} containerInfo, err := docker.InspectContainer(container.Id) if err != nil { log.Error(err) continue } for _, bind := range containerInfo.HostConfig.Binds { var ( arr = strings.Split(bind, ":") mount Mount ) mount.ContainerId = containerInfo.Id switch len(arr) { case 1: mount.MountToPath = bind mount.Writable = true case 2: mount.hostPath = arr[0] mount.MountToPath = arr[1] mount.Writable = true case 3: mount.hostPath = arr[0] mount.MountToPath = arr[1] switch arr[2] { case "ro": mount.Writable = false case "rw": mount.Writable = true default: continue } default: continue } mount.ContainerName = strings.TrimPrefix(containerInfo.Name, "/") localMounts[mount.MountToPath] = &mount } for mountToPath, hostPath := range containerInfo.Volumes { if _, exists := localMounts[mountToPath]; !exists { localMounts[mountToPath] = &Mount{ hostPath: hostPath, MountToPath: mountToPath, ContainerId: containerInfo.Id, ContainerName: strings.TrimPrefix(containerInfo.Name, "/"), Writable: containerInfo.VolumesRW[mountToPath], } } } for _, mount := range localMounts { mounts = append(mounts, mount) } } return mounts, nil }
func loginRegistry(ctx *cobra.Command, args []string) { reg := client.INDEX_SERVER if len(args) > 0 { reg = args[0] } config, err := client.LoadConfig(configPath) if err != nil { log.Fatal(err) } ctx.Printf("Log in to a Docker registry at %s\n", reg) registry, _ := config.GetRegistry(reg) authConfig := api.AuthConfig{ ServerAddress: registry.Registry, } promptDefault := func(prompt string, configDefault string) { if configDefault == "" { ctx.Printf("%s: ", prompt) } else { ctx.Printf("%s (%s): ", prompt, configDefault) } } readInput := func() string { reader := bufio.NewReader(os.Stdin) line, _, err := reader.ReadLine() if err != nil { log.Fatal(err) } return string(line) } promptDefault("Username", registry.Username) authConfig.Username = readInput() if authConfig.Username == "" { authConfig.Username = registry.Username } ctx.Print("Password: "******"Email", registry.Email) authConfig.Email = readInput() if authConfig.Email == "" { authConfig.Email = registry.Email } docker, err := client.NewDockerClient(configPath, hostName, ctx.Out()) if err != nil { log.Fatal(err) } credentials, err := docker.Auth(&authConfig) if err != nil { log.Fatal(err) } registry.Username = authConfig.Username registry.Email = authConfig.Email registry.Credentials = credentials config.SetRegistry(registry) if err := config.SaveConfig(configPath); err != nil { log.Fatal(err) } ctx.Println("Login Succeeded!") listRegistries(ctx, args) }
func showVersion(ctx *cobra.Command, args []string) { data := map[string]api.Version{} data[APP_NAME] = api.Version{ Version: version.APP_VERSION, ApiVersion: api.API_VERSION, GoVersion: runtime.Version(), GitCommit: version.GIT_COMMIT, Os: runtime.GOOS, KernelVersion: "", Arch: runtime.GOARCH, } var e error docker, err := client.NewDockerClient(configPath, hostName, ctx.Out()) if err != nil { e = err goto Display } { dockerVersion, err := docker.Version() if err != nil { e = err goto Display } data["Docker Server"] = *dockerVersion } Display: if boolYAML || boolJSON { if err := FormatPrint(ctx.Out(), data); err != nil { log.Fatal(err) } if e != nil { log.Fatal(e) } return } var items [][]string for key, value := range data { out := []string{ key, value.Version, value.ApiVersion, value.GoVersion, value.GitCommit, value.Os, value.KernelVersion, value.Arch, } items = append(items, out) } header := []string{ "", "Version", "API Version", "Go Version", "Git commit", "OS", "Kernel Version", "Arch", } PrintInTable(ctx.Out(), header, items, 0, tablewriter.ALIGN_LEFT) if e != nil { log.Fatal(e) } }