为 Docker 启用 IPv6

Author Avatar
秋のかえで 1月 19, 2023
  • 在其它设备中阅读本文章

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/