func releasePort(bnd netutils.PortBinding) error { // Construct the host side transport address host, err := bnd.HostAddr() if err != nil { return err } return portMapper.Unmap(host) }
func allocatePort(bnd *netutils.PortBinding, containerIP, defHostIP net.IP, ulPxyEnabled bool) error { var ( host net.Addr err error ) // Store the container interface address in the operational binding bnd.IP = containerIP // Adjust the host address in the operational binding if len(bnd.HostIP) == 0 { bnd.HostIP = defHostIP } // Construct the container side transport address container, err := bnd.ContainerAddr() if err != nil { return err } // Try up to maxAllocatePortAttempts times to get a port that's not already allocated. for i := 0; i < maxAllocatePortAttempts; i++ { if host, err = portMapper.Map(container, bnd.HostIP, int(bnd.HostPort), ulPxyEnabled); err == nil { break } // There is no point in immediately retrying to map an explicitly chosen port. if bnd.HostPort != 0 { logrus.Warnf("Failed to allocate and map port %d: %s", bnd.HostPort, err) break } logrus.Warnf("Failed to allocate and map port: %s, retry: %d", err, i+1) } if err != nil { return err } // Save the host port (regardless it was or not specified in the binding) switch netAddr := host.(type) { case *net.TCPAddr: bnd.HostPort = uint16(host.(*net.TCPAddr).Port) return nil case *net.UDPAddr: bnd.HostPort = uint16(host.(*net.UDPAddr).Port) return nil default: // For completeness return ErrUnsupportedAddressType(fmt.Sprintf("%T", netAddr)) } }
func (container *Container) buildCreateEndpointOptions() ([]libnetwork.EndpointOption, error) { var ( portSpecs = make(nat.PortSet) bindings = make(nat.PortMap) pbList []netutils.PortBinding exposeList []netutils.TransportPort createOptions []libnetwork.EndpointOption ) if container.Config.PortSpecs != nil { if err := migratePortMappings(container.Config, container.hostConfig); err != nil { return nil, err } container.Config.PortSpecs = nil if err := container.WriteHostConfig(); err != nil { return nil, err } } if container.Config.ExposedPorts != nil { portSpecs = container.Config.ExposedPorts } if container.hostConfig.PortBindings != nil { for p, b := range container.hostConfig.PortBindings { bindings[p] = []nat.PortBinding{} for _, bb := range b { bindings[p] = append(bindings[p], nat.PortBinding{ HostIp: bb.HostIp, HostPort: bb.HostPort, }) } } } container.NetworkSettings.PortMapping = nil ports := make([]nat.Port, len(portSpecs)) var i int for p := range portSpecs { ports[i] = p i++ } nat.SortPortMap(ports, bindings) for _, port := range ports { expose := netutils.TransportPort{} expose.Proto = netutils.ParseProtocol(port.Proto()) expose.Port = uint16(port.Int()) exposeList = append(exposeList, expose) pb := netutils.PortBinding{Port: expose.Port, Proto: expose.Proto} binding := bindings[port] for i := 0; i < len(binding); i++ { pbCopy := pb.GetCopy() pbCopy.HostPort = uint16(nat.Port(binding[i].HostPort).Int()) pbCopy.HostIP = net.ParseIP(binding[i].HostIp) pbList = append(pbList, pbCopy) } if container.hostConfig.PublishAllPorts && len(binding) == 0 { pbList = append(pbList, pb) } } createOptions = append(createOptions, libnetwork.CreateOptionPortMapping(pbList), libnetwork.CreateOptionExposedPorts(exposeList)) if container.Config.MacAddress != "" { mac, err := net.ParseMAC(container.Config.MacAddress) if err != nil { return nil, err } genericOption := options.Generic{ netlabel.MacAddress: mac, } createOptions = append(createOptions, libnetwork.EndpointOptionGeneric(genericOption)) } return createOptions, nil }