Docker环境下绑定IPv6回环地址::1失败,附asyncio代码及报错
我之前也踩过这个Docker里用asyncio绑定IPv6回环地址的坑,刚好和你遇到的情况一样——运行这段代码时直接抛出异常:
import asyncio async def handle_echo(reader, writer): data = await reader.read(100) writer.write(data) await writer.drain() writer.close() loop = asyncio.get_event_loop() server = loop.run_until_complete(asyncio.start_server(handle_echo, '::1', 8888)) loop.run_forever()
报错的关键片段是:
Traceback (most recent call last):
File "/home/dev/lib/aioimaplib/aioimaplib/tests/echo.py", line 10, in
server = loop.run_until_complete(asyncio.star...
其实问题出在Docker的网络配置上,给你几个实用的解决思路:
先开启Docker的IPv6支持
默认情况下Docker是禁用IPv6的,容器根本没法识别IPv6地址。你需要编辑Docker的守护进程配置文件/etc/docker/daemon.json,添加以下内容:{ "ipv6": true, "fixed-cidr-v6": "fd00::/80" }保存后重启Docker服务:
systemctl restart docker,这样容器才能正常处理IPv6网络请求。改用IPv6通配地址绑定(最推荐)
没必要死磕回环地址::1,把代码里的绑定地址改成::(IPv6的通配地址),这样服务会监听容器所有可用的IPv6接口,不管是内部访问还是映射到宿主机都能用:server = loop.run_until_complete(asyncio.start_server(handle_echo, '::', 8888))这种方式不需要改太多配置,兼容性最好。
用host网络模式强制共享宿主机网络
如果你非要绑定::1,可以在启动容器时加上--network host参数,让容器直接使用宿主机的网络栈。这样容器里的::1就和宿主机的回环地址完全一致,代码不需要修改就能正常运行。不过这种方式会失去容器的网络隔离性,适合测试或者特殊场景使用。
内容的提问来源于stack exchange,提问作者Bruno Thomas

