我相信不少开发者正在或曾经使用 docker 起后端开发环境,那么肯定有不少人遇到过这个莫名奇妙的错误:
Error invoking remote method ‘docker-start-container’: Error: (HTTP code 500) server error - Ports are not available: listen tcp 0.0.0.0:xxxx: bind: An attempt was made to access a socket in a way forbidden by access permissions.
上面的图片来自网络,我当时忙着处理事务忘记截图了。
我一开始遇到这种问题是直接尝试重启(大多数时候能够解决该问题),直到这一次重启也不管用了,我才重新开始审视这个错误。
考虑到您可能没有耐心看下去(我相信大多数人遇到这个问题的时候没空细究起因),我先把解决方案贴在前面。
# 解决方案
# 正确的解决方案
简单地重新设置“TCP 动态端口范围”,以便 Hyper-V 只保留我们设置的范围内的端口。您可以通过以管理员权限运行以下命令将“TCP 动态端口范围”重置为 49152–65535,但如果您认为它太大,也可以将其更改为较小的范围。
请在命令行中执行下列命令设置动态端口范围:
然后重启电脑。
# 错误的解决方案
来自 StackOverflow 的错误解决方案 在该问题的高赞回答中,他使用了以下命令:
这命令的实质是简化版的重启电脑,让 Hyper-V 初始化一些随机端口来保留,如果没有它仍然没有释放你所需要的端口,你可能不得不再做这样的操作。也就是因此,该回答下面有些人回复有用,有些人回复没用,就是因为这种解决方式解决问题的概率非常的随机。
# 错误背景
进入正题,为什么会发生这个错误?这里不得不说明一下两个和问题有关的特性。
- Windows 中个东西叫做“TCP 动态端口范围”,这个范围内的端口有时候会被一些服务占用。在 Windows Vista(或 Windows Server 2008)之前,动态端口范围是 1025 到 5000;在其之后的版本中,新的默认起始端口为 49152,新的默认结束端口为 65535。
- 如果安装了 Hyper-V,则 Hyper-V 会保留一些随机端口号供 Windows 容器主机网络服务使用。
一般情况(正常情况下)Hyper-V 会在“TCP 动态端口范围”中预留一些随机的端口号,但是预留的端口号一般都很大,所以即使预留了成百上千个端口,也影响不大。但是 Windows 自动更新有时会出错(万恶的自动更新),把“TCP 动态端口范围”起始端口被重置为 1024,导致 Hyper-V 在预留端口的时候占用了常用端口号,使得一些常用端口因为被预留而无法使用。
你可以使用命令 netsh int ipv4 show dynamicport tcp
查看当前的“TCP 动态端口范围”,还可使用 netsh int ipv4 show excludeportrange protocol=tcp
查看当前已经被征用的端口。