背景
由于 Windows 的 Docker 是依赖 Hyper-V 的,但在启用 Hyper-V 后,会产生各种端口莫名被占用的问题。
例如启动 Docker 时会报错(端口随机在一个小范围内波动的):
Error starting userland proxy: Bind for 0.0.0.0:50022: unexpected error Permission denied.
电脑重启几次之后,以上报错可能会消失,好像一切又恢复正常。
Docker 的服务端口会在
50000 - 50059
中随机分配
分析
表面看上去像是端口 50022 被占用,但是当在 PowerShell 中查看端口占用情况时:
netstat -ano | findstr 50022
发现这个端口并未被某个进程使用。这说明这些端口可能是被系统保留了,比如 Hyper-V。
根据 List of TCP and UDP port numbers 的说明,tcp/udp 端口号被分为 3 段:
端口类型 | 范围 | 用途 |
---|---|---|
周知端口 | 0 - 1023 |
提供广泛使用的网络服务类型的系统进程使用 |
注册端口 | 1024 - 49151 |
给用户进程或应用程序使用 |
动态端口 | 49152 - 65535 |
用于私有或定制服务、临时目的以及临时端口的自动分配 |
见 Service overview and network port requirements for Windows,Windows 将
49152 - 65535
划分为 动态端口
Hyper-V 会将动态端口中的几段范围的端口保留给自己使用,用户的应用程序无法使用这些端口。
可以执行命令 netsh int ipv4 show dynamicport tcp
查看动态端口范围:
再执行命令 netsh int ipv4 show excludedport tcp
查看被系统保留的端口(其中标记 *
的端口被 Administrator 排除):
可以看到,50000 - 50059
等范围端口被系统保留了(即用户不可用),且 Administrator 没有排除任何端口,导致用户启动 Docker 时,当端口落到这些系统保留范围内时,就会因为端口被占用而启动失败。
解决
知道原因后就很容易解决了:只需要用 Administrator 排除 50000 - 50059
范围的端口,使得 Docker 可以使用即可。
具体方法为:
- 停止 Docker 进程(最好重启电脑)
- 在 powershell 执行以下命令设置排除端口范围:
# 保留 50000 - 50059 这 60 个端口给应用程序使用
netsh int ipv4 add excludedportrange protocol=tcp startport=50000 numberofports=60
- 重启电脑,使得排除策略生效
- 执行命令
netsh int ipv4 show excludedport tcp
可以看到50000 - 50059
已被排除(不被系统保留),此时即可成功启动 Docker