Documentation
¶
Overview ¶
Package portmap publishes a container's ports on the host: `wctr run -p`, Docker's HostConfig.PortBindings and PublishAllPorts.
A container has no host socket of its own: its listeners live on the engine's networks (netdriver). So a published port is a listener the daemon opens on the host -- through a Host, which is net.Listen natively and something else in a browser -- and every connection it accepts is dialed into the container through the container's own endpoint. Nothing is routed and no packet is rewritten; a connection is copied, both ways, like Docker's userland proxy.
⛔ One difference from Docker, on purpose: a binding that names no host address listens on 127.0.0.1, not on every address. A training lab's container should not become a service on the machine's network because somebody typed `-p 8080:80`; `-p 0.0.0.0:8080:80` says so when it is meant.
Index ¶
Constants ¶
const MaxBindings = 1024
MaxBindings bounds one container's bindings: each is a host listener.
const MaxDatagram = 8 << 10
MaxDatagram bounds one datagram, as the engine's networks do.
Variables ¶
var DefaultHostIP = netip.AddrFrom4([4]byte{127, 0, 0, 1})
DefaultHostIP is the address a binding that names none listens on.
var DefaultLimits = Limits{MaxConns: 128, MaxSessions: 256, UDPIdle: 90 * time.Second, DialTimeout: 5 * time.Second}
DefaultLimits are Docker's UDP timeout (90 s) and bounds sized for a classroom, not a production load balancer.
var ErrAllocated = errors.New("port is already allocated")
ErrAllocated is a host port somebody else holds.
var ErrInvalid = errors.New("invalid port specification")
ErrInvalid is a port, a binding or a specification that cannot be.
Functions ¶
This section is empty.
Types ¶
type APIBinding ¶
APIBinding is Docker's PortBinding: strings, an empty HostIp for the default address, an empty HostPort for one the system picks.
type APIMap ¶
type APIMap map[string][]APIBinding
APIMap is Docker's PortMap: "80/tcp" -> bindings, null for a port only exposed.
type Binding ¶
type Binding struct {
// HostIP is the address to listen on; the zero Addr is DefaultHostIP.
HostIP netip.Addr
// HostPort, HostPortEnd: a port, a range to take the first free one
// from, or 0 for one the system picks.
HostPort, HostPortEnd uint16
}
Binding is where a container port is published on the host.
func ParseBinding ¶
ParseBinding reads the API's PortBinding: a HostIp ("" for the default) and a HostPort ("", "8080", "8000-8010").
func (Binding) API ¶
func (b Binding) API() APIBinding
API is the binding as the Engine API writes it.
type Dialer ¶
Dialer reaches the container: its own endpoint, dialing 127.0.0.1, so a port is reached on whichever of its networks it listens.
type Host ¶
type Host interface {
Listen(ctx context.Context, network string, addr netip.AddrPort) (net.Listener, error)
ListenPacket(ctx context.Context, network string, addr netip.AddrPort) (net.PacketConn, error)
}
Host is where published ports listen: the machine's sockets for wctrd (OS), something the page provides in a browser.
type Key ¶
Key is a container port and its protocol: Docker's "80/tcp".
type Limits ¶
type Limits struct {
// MaxConns is the connections one TCP binding proxies at once; the next
// is closed as soon as it is accepted.
MaxConns int
// MaxSessions is the UDP clients one binding keeps at once; a datagram
// from another is dropped, as a full socket buffer drops.
MaxSessions int
// UDPIdle ends a UDP client's session after this long without traffic.
UDPIdle time.Duration
// DialTimeout bounds reaching the container.
DialTimeout time.Duration
}
Limits bound what one published port may hold.
type Map ¶
Map is a container's bindings, by port. A port in it with no binding is exposed and not published (Docker's `"2377/tcp": null`).
func ParseSpec ¶
ParseSpec reads one `-p` value, as Docker does (github.com/docker/go-connections/nat.ParsePortSpec):
containerPort[/proto] hostPort:containerPort[/proto] ip:hostPort:containerPort[/proto] ip: [::1] for IPv6 ip::containerPort[/proto] a host port the system picks
Ports may be ranges of the same length ("8000-8010:80-90"); a host range with a single container port is where to take a free one from.
func ParseSpecs ¶
ParseSpecs reads every `-p` value into one map.
func (Map) Exposed ¶
Exposed adds ports to m as exposed (no binding), keeping bindings it already has: Docker's Config.ExposedPorts and the image's.
func (Map) MarshalJSON ¶
MarshalJSON writes the Engine API's shape.
func (Map) PublishAll ¶
PublishAll is m with every port that has no binding given one the system picks: run -P, HostConfig.PublishAllPorts.
func (*Map) UnmarshalJSON ¶
UnmarshalJSON reads it, validating every key and binding.
type Set ¶
type Set struct {
// contains filtered or unexported fields
}
Set is one container's published ports while it runs.
func Publish ¶
Publish opens every binding of m and proxies it to the container, or opens none: a binding that cannot be had closes the others and says which ("Bind for 127.0.0.1:8080 failed: port is already allocated", as Docker words it). A port with no binding is only exposed.