为 Docker 启用 IPv6
IPv6 目前已经有了一定的普及度,为服务部署 IPv6 支持是一个重要的需求。本文将介绍如何为 Docker 启用 IPv6 支持。
分配已有地址
这是 Docker 目前正式支持的方式,如果你有一段大于 128 位的 IPv6 地址,你可以将它分配给容器。
可以通过修改 /etc/docker/daemon.json
文件或 Docker 启动命令参数来为 Docker 默认的 bridge
网络启用 IPv6:
{
"ipv6": true,
"fixed-cidr-v6": "2001:db8:1::/64"
}
也可以通过以下命令创建支持 IPv6 的 bridge 网络:
docker network create --ipv6 --subnet 2001:db8:1::/64 <name>
但是,这样做会带来一个显著的问题。如果给容器分配公共 IPv6 地址会使容器的端口映射不受 Docker 控制,这可能导致一些服务暴露在公共网络上。同时部分云服务商 (如 Azure)只给虚拟机分配了一个 128 位的 IPv6 公共地址,这样就没有多余的地址分配给容器了。
使用 IPv6 NAT
Docker 目前实验性地引入了对 IPv6 NAT 的支持,通过为容器分配 Unique Local Address 地址可以很轻松地解决上述问题。
可以通过修改 /etc/docker/daemon.json
文件或命令参数来启用这一特性(因为该特性目前为实验性,所以需要启用 experimental
):
{
"ip6tables": true,
"experimental": true
}
这时,我们只需要为 Docker 网络分配 ULA 地址即可。RFC 4193 推荐使用随机生成的方式以免合并网络时带来地址冲突的麻烦。(你可以使用这个 ULA Generator,它会根据 MAC 地址和时间戳来生成 ULA。)
同理,我们可以通过相同的方式修改 /etc/docker/daemon.json
文件或 Docker 启动命令参数为默认的 bridge
网络启用 Ipv6 支持和通过命令创建支持 IPv6 的 Docker 网络:
{
"ipv6": true,
"fixed-cidr-v6": "fd00::/64",
"ip6tables": true,
"experimental": true
}
docker network create --ipv6 --subnet fd00::/64 <name>
需要注意的是默认情况下在 gai.conf
中 ULA 的优先级低于 IPv4,所以部分使用 libc
的程序会优先使用 IPv4 而非 IPv6。可以通过修改 /etc/gai.conf
文件来修改优先级。
Docker Compose 配置
由于 Docker Swarm 目前并不支持 IPv6。所以版本为 3
的 Docker Compose 配置并不支持创建使用 IPv6 的网络。我们可以通过版本为 2
的配置或者使用外部的 Docker 网络来解决这个问题。以下是配置示例:
version: '2.4'
networks:
bridge:
driver: bridge
enable_ipv6: true
ipam:
config:
- subnet: 2001:db8:1::/64
gateway: 2001:db8:1::1
故障排除
如果通过上述操作之后,你的 IPv6 网络没有正常工作,可能是因为没有启用 IPv6 转发。可以通过修改 /etc/sysctl.conf
,/etc/sysctl.d/
文件夹下的文件或使用 sysctl
命令来启用 IPv6 转发:
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.default.forwarding = 1
修改文件后可使用 sysctl -p
命令使其立即生效。
如果你使用了路由通告(Router Advertisements),那么启用 IPv6 转发可能使其不工作。将 net.ipv6.conf.eth0.accept_ra
可使其在 IPv6 转发开启时正常工作。其中 eth0
为接受路由通告的网卡的名称。
net.ipv6.conf.eth0.accept_ra = 2
本文使用 CC BY-NC-SA 4.0 授权
本文链接:https://blog.akinokae.de/archives/docker-ipv6/