我正在运行一个小型 arm 板,在我们的本地网络中提供一些服务。当我尝试了解 docker 的 ipv6 支持时,我对第一次测试的结果感到很困惑。
我的网络由使用 dhcpv6 的单一路由控制,每个客户端都有 2 个有效的全局 ipv6 地址(还有 1 个本地 ipv4),并受到路由器防火墙的保护(不允许从互联网向客户端发出请求)。
arm 主板运行的是 ubuntu 16.04,具有有效的 ipv6 地址并启用了隐私扩展。
所有的docker容器都使用默认的桥接网络,无需进行任何调整。
在 docker 主机上
netstat -tulpen|grep docker
节目
tcp6 0 0 :::8080 :::* LISTEN 0 22490 1559/docker-proxy
没有一个 IPv4 服务正在监听。
在这个docker容器中,同样的netstat请求给出
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 0 23955 8/nginx
tcp6 0 0 :::80 :::* LISTEN 0 23956 8/nginx
Nginx 正在监听 ipv6 和 ipv4 - 端口 80 暴露给端口 8080,
docker run (...) -p 8080:80 (...)
检查桥梁网络
docker network inspect bridge
显示默认本地桥接
(...)
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
(...)
"b10cf3750252daf0ba11a59cfcd64c72194adcaacd4b9b5df17fae0f53fc4f00": {
"Name": "ng",
"EndpointID": "f42de3590072dec2b0d3fae61fc89aeffcb8e6e716b27f5736272fcc8f94f643",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
}
(...)
现在回答我的问题:
据我了解,docker bridge ipv6 的配置已禁用,docker 容器没有 ipv6 - 只有 ipv4。Nginx 监听 ipv4 和 ipv6 - 忽略没有可用的 ipv6 这一事实。
为什么在端口 8080 上公开的主机上的 nginx 服务仅列为可通过 ipv6 访问?
使用另一个网络客户端验证这一点
curl -g -6 http://[DOCKER_HOST_IPV6]:8080
curl http://[DOCKER_HOST_IPV4]:8080
显示该服务可用于 ipv6 和 ipv4 - 为什么 netstat 不将该服务显示为 ipv4 服务?
如果在桥接网络配置中禁用了 ipv6,那么服务如何可达?
我有另一个在 udp 1194 上运行 openvpn 的容器。我将服务器配置为使用 udp6,并在容器内使用 netstat 进行验证。此容器使用 -p 标志以相同的方式公开,但在主机上根本不可用。我如何正确桥接此服务?
答案1
这不是监听 ipv6 的 nginx 容器(顺便说一句,您在容器中看到的 tcp6 套接字绑定在其 fe80:: 和 ::1 上,并且无法从容器外部访问)。这是管理主机端口的 docker-proxy 进程。当您使用“-p 8080:80”时,docker-proxy 会在主机 ::0 上绑定一个监听端口 8080 的 tcp6 套接字(并且 tcp6 套接字也接受 tcp4)。
因此,在 docker 上禁用 ipv6 支持(默认)意味着您的容器仅分配了 ipv4,但 docker-proxy 会将 v6 “翻译”为 v4:
(ipv6 世界) -> docker 主机 ipv6:8080 -> [docker-proxy] -> nginx 容器 ipv4:80