func (daemon *Daemon) verifyHostConfig(hostConfig *runconfig.HostConfig) ([]string, error) { var warnings []string if hostConfig == nil { return warnings, nil } for port := range hostConfig.PortBindings { _, portStr := nat.SplitProtoPort(string(port)) if _, err := nat.ParsePort(portStr); err != nil { return warnings, fmt.Errorf("Invalid port specification: %s", portStr) } } if hostConfig.LxcConf.Len() > 0 && !strings.Contains(daemon.ExecutionDriver().Name(), "lxc") { return warnings, fmt.Errorf("Cannot use --lxc-conf with execdriver: %s", daemon.ExecutionDriver().Name()) } if hostConfig.Memory != 0 && hostConfig.Memory < 4194304 { return warnings, fmt.Errorf("Minimum memory limit allowed is 4MB") } if hostConfig.Memory > 0 && !daemon.SystemConfig().MemoryLimit { warnings = append(warnings, "Your kernel does not support memory limit capabilities. Limitation discarded.") hostConfig.Memory = 0 } if hostConfig.Memory > 0 && hostConfig.MemorySwap != -1 && !daemon.SystemConfig().SwapLimit { warnings = append(warnings, "Your kernel does not support swap limit capabilities, memory limited without swap.") hostConfig.MemorySwap = -1 } if hostConfig.Memory > 0 && hostConfig.MemorySwap > 0 && hostConfig.MemorySwap < hostConfig.Memory { return warnings, fmt.Errorf("Minimum memoryswap limit should be larger than memory limit, see usage.") } if hostConfig.Memory == 0 && hostConfig.MemorySwap > 0 { return warnings, fmt.Errorf("You should always set the Memory limit when using Memoryswap limit, see usage.") } if hostConfig.CpuPeriod > 0 && !daemon.SystemConfig().CpuCfsPeriod { warnings = append(warnings, "Your kernel does not support CPU cfs period. Period discarded.") hostConfig.CpuPeriod = 0 } if hostConfig.CpuQuota > 0 && !daemon.SystemConfig().CpuCfsQuota { warnings = append(warnings, "Your kernel does not support CPU cfs quota. Quota discarded.") hostConfig.CpuQuota = 0 } if hostConfig.BlkioWeight > 0 && (hostConfig.BlkioWeight < 10 || hostConfig.BlkioWeight > 1000) { return warnings, fmt.Errorf("Range of blkio weight is from 10 to 1000.") } if hostConfig.OomKillDisable && !daemon.SystemConfig().OomKillDisable { hostConfig.OomKillDisable = false return warnings, fmt.Errorf("Your kernel does not support oom kill disable.") } return warnings, nil }
func (settings *NetworkSettings) PortMappingAPI() *engine.Table { var outs = engine.NewTable("", 0) for port, bindings := range settings.Ports { p, _ := nat.ParsePort(port.Port()) if len(bindings) == 0 { out := &engine.Env{} out.SetInt("PrivatePort", p) out.Set("Type", port.Proto()) outs.Add(out) continue } for _, binding := range bindings { out := &engine.Env{} h, _ := nat.ParsePort(binding.HostPort) out.SetInt("PrivatePort", p) out.SetInt("PublicPort", h) out.Set("Type", port.Proto()) out.Set("IP", binding.HostIp) outs.Add(out) } } return outs }
func (daemon *Daemon) Containers(job *engine.Job) error { var ( foundBefore bool displayed int all = job.GetenvBool("all") since = job.Getenv("since") before = job.Getenv("before") n = job.GetenvInt("limit") size = job.GetenvBool("size") psFilters filters.Args filtExited []int ) containers := []types.Container{} psFilters, err := filters.FromParam(job.Getenv("filters")) if err != nil { return err } if i, ok := psFilters["exited"]; ok { for _, value := range i { code, err := strconv.Atoi(value) if err != nil { return err } filtExited = append(filtExited, code) } } if i, ok := psFilters["status"]; ok { for _, value := range i { if value == "exited" { all = true } } } names := map[string][]string{} daemon.ContainerGraph().Walk("/", func(p string, e *graphdb.Entity) error { names[e.ID()] = append(names[e.ID()], p) return nil }, 1) var beforeCont, sinceCont *Container if before != "" { beforeCont, err = daemon.Get(before) if err != nil { return err } } if since != "" { sinceCont, err = daemon.Get(since) if err != nil { return err } } errLast := errors.New("last container") writeCont := func(container *Container) error { container.Lock() defer container.Unlock() if !container.Running && !all && n <= 0 && since == "" && before == "" { return nil } if !psFilters.Match("name", container.Name) { return nil } if !psFilters.Match("id", container.ID) { return nil } if !psFilters.MatchKVList("label", container.Config.Labels) { return nil } if before != "" && !foundBefore { if container.ID == beforeCont.ID { foundBefore = true } return nil } if n > 0 && displayed == n { return errLast } if since != "" { if container.ID == sinceCont.ID { return errLast } } if len(filtExited) > 0 { shouldSkip := true for _, code := range filtExited { if code == container.ExitCode && !container.Running { shouldSkip = false break } } if shouldSkip { return nil } } if !psFilters.Match("status", container.State.StateString()) { return nil } displayed++ newC := types.Container{ ID: container.ID, Names: names[container.ID], } img := container.Config.Image _, tag := parsers.ParseRepositoryTag(container.Config.Image) if tag == "" { img = utils.ImageReference(img, graph.DEFAULTTAG) } newC.Image = img if len(container.Args) > 0 { args := []string{} for _, arg := range container.Args { if strings.Contains(arg, " ") { args = append(args, fmt.Sprintf("'%s'", arg)) } else { args = append(args, arg) } } argsAsString := strings.Join(args, " ") newC.Command = fmt.Sprintf("%s %s", container.Path, argsAsString) } else { newC.Command = fmt.Sprintf("%s", container.Path) } newC.Created = int(container.Created.Unix()) newC.Status = container.State.String() newC.Ports = []types.Port{} for port, bindings := range container.NetworkSettings.Ports { p, _ := nat.ParsePort(port.Port()) if len(bindings) == 0 { newC.Ports = append(newC.Ports, types.Port{ PrivatePort: p, Type: port.Proto(), }) continue } for _, binding := range bindings { h, _ := nat.ParsePort(binding.HostPort) newC.Ports = append(newC.Ports, types.Port{ PrivatePort: p, PublicPort: h, Type: port.Proto(), IP: binding.HostIp, }) } } if size { sizeRw, sizeRootFs := container.GetSize() newC.SizeRw = int(sizeRw) newC.SizeRootFs = int(sizeRootFs) } newC.Labels = container.Config.Labels containers = append(containers, newC) return nil } for _, container := range daemon.List() { if err := writeCont(container); err != nil { if err != errLast { return err } break } } sort.Sort(sort.Reverse(ByCreated(containers))) if err = json.NewEncoder(job.Stdout).Encode(containers); err != nil { return err } return nil }
// Allocate an external port and map it to the interface func AllocatePort(id string, port nat.Port, binding nat.PortBinding) (nat.PortBinding, error) { var ( ip = defaultBindingIP proto = port.Proto() containerPort = port.Int() network = currentInterfaces.Get(id) ) if binding.HostIp != "" { ip = net.ParseIP(binding.HostIp) if ip == nil { return nat.PortBinding{}, fmt.Errorf("Bad parameter: invalid host ip %s", binding.HostIp) } } // host ip, proto, and host port var container net.Addr switch proto { case "tcp": container = &net.TCPAddr{IP: network.IP, Port: containerPort} case "udp": container = &net.UDPAddr{IP: network.IP, Port: containerPort} default: return nat.PortBinding{}, fmt.Errorf("unsupported address type %s", proto) } // // Try up to 10 times to get a port that's not already allocated. // // In the event of failure to bind, return the error that portmapper.Map // yields. // var ( host net.Addr err error ) hostPort, err := nat.ParsePort(binding.HostPort) if err != nil { return nat.PortBinding{}, err } for i := 0; i < MaxAllocatedPortAttempts; i++ { if host, err = portMapper.Map(container, ip, hostPort); err == nil { break } // There is no point in immediately retrying to map an explicitly // chosen port. if hostPort != 0 { logrus.Warnf("Failed to allocate and map port %d: %s", hostPort, err) break } logrus.Warnf("Failed to allocate and map port: %s, retry: %d", err, i+1) } if err != nil { return nat.PortBinding{}, err } network.PortMappings = append(network.PortMappings, host) switch netAddr := host.(type) { case *net.TCPAddr: return nat.PortBinding{HostIp: netAddr.IP.String(), HostPort: strconv.Itoa(netAddr.Port)}, nil case *net.UDPAddr: return nat.PortBinding{HostIp: netAddr.IP.String(), HostPort: strconv.Itoa(netAddr.Port)}, nil default: return nat.PortBinding{}, fmt.Errorf("unsupported address type %T", netAddr) } }
func (daemon *Daemon) Containers(config *ContainersConfig) ([]*types.Container, error) { var ( foundBefore bool displayed int all = config.All n = config.Limit psFilters filters.Args filtExited []int ) containers := []*types.Container{} psFilters, err := filters.FromParam(config.Filters) if err != nil { return nil, err } if i, ok := psFilters["exited"]; ok { for _, value := range i { code, err := strconv.Atoi(value) if err != nil { return nil, err } filtExited = append(filtExited, code) } } if i, ok := psFilters["status"]; ok { for _, value := range i { if value == "exited" || value == "created" { all = true } } } names := map[string][]string{} daemon.ContainerGraph().Walk("/", func(p string, e *graphdb.Entity) error { names[e.ID()] = append(names[e.ID()], p) return nil }, 1) var beforeCont, sinceCont *Container if config.Before != "" { beforeCont, err = daemon.Get(config.Before) if err != nil { return nil, err } } if config.Since != "" { sinceCont, err = daemon.Get(config.Since) if err != nil { return nil, err } } errLast := errors.New("last container") writeCont := func(container *Container) error { container.Lock() defer container.Unlock() if !container.Running && !all && n <= 0 && config.Since == "" && config.Before == "" { return nil } if !psFilters.Match("name", container.Name) { return nil } if !psFilters.Match("id", container.ID) { return nil } if !psFilters.MatchKVList("label", container.Config.Labels) { return nil } if config.Before != "" && !foundBefore { if container.ID == beforeCont.ID { foundBefore = true } return nil } if n > 0 && displayed == n { return errLast } if config.Since != "" { if container.ID == sinceCont.ID { return errLast } } if len(filtExited) > 0 { shouldSkip := true for _, code := range filtExited { if code == container.ExitCode && !container.Running { shouldSkip = false break } } if shouldSkip { return nil } } if !psFilters.Match("status", container.State.StateString()) { return nil } displayed++ newC := &types.Container{ ID: container.ID, Names: names[container.ID], } newC.Image = container.Config.Image if len(container.Args) > 0 { args := []string{} for _, arg := range container.Args { if strings.Contains(arg, " ") { args = append(args, fmt.Sprintf("'%s'", arg)) } else { args = append(args, arg) } } argsAsString := strings.Join(args, " ") newC.Command = fmt.Sprintf("%s %s", container.Path, argsAsString) } else { newC.Command = fmt.Sprintf("%s", container.Path) } newC.Created = int(container.Created.Unix()) newC.Status = container.State.String() newC.HostConfig.NetworkMode = string(container.HostConfig().NetworkMode) newC.Ports = []types.Port{} for port, bindings := range container.NetworkSettings.Ports { p, _ := nat.ParsePort(port.Port()) if len(bindings) == 0 { newC.Ports = append(newC.Ports, types.Port{ PrivatePort: p, Type: port.Proto(), }) continue } for _, binding := range bindings { h, _ := nat.ParsePort(binding.HostPort) newC.Ports = append(newC.Ports, types.Port{ PrivatePort: p, PublicPort: h, Type: port.Proto(), IP: binding.HostIp, }) } } if config.Size { sizeRw, sizeRootFs := container.GetSize() newC.SizeRw = int(sizeRw) newC.SizeRootFs = int(sizeRootFs) } newC.Labels = container.Config.Labels containers = append(containers, newC) return nil } for _, container := range daemon.List() { if err := writeCont(container); err != nil { if err != errLast { return nil, err } break } } return containers, nil }