示例#1
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)
}
示例#2
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
}
示例#3
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)
}
示例#4
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)
	}
}
示例#5
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)
	}
}
示例#6
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
}