示例#1
0
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
}
示例#2
0
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")
	}
}
示例#3
0
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)
	}
}
示例#4
0
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")
	}
}
示例#5
0
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)
}
示例#6
0
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)
}
示例#7
0
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)
}
示例#8
0
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)
	}
}
示例#9
0
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)
}
示例#10
0
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)
	}
}
示例#11
0
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
}
示例#12
0
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)
	}
}
示例#13
0
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)
		}
	}
}
示例#14
0
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)
	}
}
示例#15
0
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")
	}
}
示例#16
0
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])
	}
}
示例#17
0
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")
	}
}
示例#18
0
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")
	}
}
示例#19
0
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
}
示例#20
0
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)
}
示例#21
0
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)
}
示例#22
0
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
}
示例#23
0
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")
}
示例#24
0
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")
}
示例#25
0
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)
}
示例#26
0
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)
}
示例#27
0
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
}
示例#28
0
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)
}
示例#29
0
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)
	}
}