新建容器时映射某些端口,如下:
主机将自动给容器的22和80映射两个端口,如:
0.0.0.0:49155->22/tcp, 0.0.0.0:49156->80/tcp
当该容器停止并且删除后,49155和49156这两个主机端口应该被释放,留给新的容器使用,但实际此时再新建容器映射端口发现,这两并未使用,而是系统自动分配这俩端口后面新的端口,比如49157...
只有docker服务重启后原来空出来的端口才会被分配。在三台不同的docker主机上做实验都是如此,貌似不是我配置的问题,不知大家的环境如何?求解!
天蓬老师2017-04-21 10:57:34
透過查看源碼docker / runtime / networkdriver / portallocator / portallocator.go
可以知道
docker的動態範圍連接埠從 49153-65535
const (
BeginPortRange = 49153
EndPortRange = 65535
)
分配埠的方式順序遞增,到最大值後,從頭開始循環
func nextPort(proto string) int {
c := currentDynamicPort[proto] + 1
if c > EndPortRange {
c = BeginPortRange
}
currentDynamicPort[proto] = c
return c
}
container銷毀時,會釋放連接埠
func ReleasePort(ip net.IP, proto string, port int) error {
.......
allocated := defaultAllocatedPorts[proto]
allocated.Remove(port)
.......
}
findNextPort
方法从nexPort
方法返回的值中,挑一个没被使用的,如果找一圈没找到,抛出ErrAllPortsAllocated
異常。
func findNextPort(proto string, allocated *collections.OrderedIntSet) (int, error) {
port := nextPort(proto)
startSearchPort := port
for allocated.Exists(port) {
port = nextPort(proto)
if startSearchPort == port {
return 0, ErrAllPortsAllocated
}
}
return port, nil
}
綜上,端口實際上已經釋放,但不會馬上再使用,除非端口資源非常緊張。
所以你看到的是正常狀況,不用但心(前提是你需要用v0.10以上版本)。
循環使用連接埠這個特性是v0.10版本加上的。 如果低於這個版本,連接埠號碼到EndPortRange
後,就只能重啟Docker了
參考: https://github.com/dotcloud/docker/pull/4949