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 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 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 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 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 }