Featured image of post 一个简单开启 Docker IPv6 的方法

一个简单开启 Docker IPv6 的方法

配图: rows of yellow lounge chairs photo – Free Image on Unsplash

IPv6 有了,运营商用 PD 协议下发了 240e:3b7:xxx:xxx::/60 这个前缀,理论上,就可以随便分配 IP 给下游设备了,虚机机之类的如果可以桥接,也是没有问题的,那 Docker 可以吗?Docker 支持 IPv6 大概有两种情况

  • 每个容器都有 IPv6 地址
  • 每个容器能访问 IPv6 网络,但是没有公网 IPv6 地址

官方对 IPv6 的支持不太积极,macOS 上的一些问题一起挂着没有解决,可能 macOS 比较特殊吧,官方文档中提到 IPv6 的支持很简单,需要修改 /etc/docker/daemon.json,加入两个选项

1
2
3
4
{
  "ipv6": true,
  "fixed-cidr-v6": "2001:db8:1::/64"
}

似乎不适用,因为这个配置是固定的前缀,而运营商给的是通过 PD 下发的动态前缀,这个方法应该主要是面向服务器应用场景的,服务器有固定的 IP,通常还有可以得到一个前缀来使用,这样就可以通过上面的方法配置使容器都得到一个公网 IPv6 地址,这样配置就满足了情况一,但是,每个容器都有公网地址,有必要吗?似乎没有什么应用场景,主要是通常一个公网 IP 都对应一套防火墙配置,而如果每个容器都有 IP 了,容器的防火墙怎么搞?而我真正想达到的目的,只是想让容器可以访问 IPv6 网络,其他无所谓。

这样就类似 IPv4 情况了,IPv4 情况下,只有一个公网 IP,容器通过 NAT 连网,防火墙只需要配置宿主机的,IPv6 也可以达到同样的效果,就是 「IPv6 NAT」,不过需要额外的一点配置

用下面配置后,重启 Docker,然后查看默认 bridge 网络的 IPv6 地址

1
2
3
4
{
  "ipv6": true,
  "fixed-cidr-v6": "fd00::/80"
}
1
docker network inspect bridge
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
[
    {
        "Name": "bridge",
        "Id": "162d1fcc6eb40abbe1d6c96d506b756082a557e5f40885d5f86ee2e49c82efc3",
        "Created": "2023-02-13T02:15:01.740262028-05:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": true,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                },
                {
                    "Subnet": "fd00::/80",
                    "Gateway": "fd00::1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

可以看到 bridge 网络已经有了正确的 IPv6 配置,用以下命令测试一下

1
docker run --network=bridge --rm -it busybox ping -6 -c4 google.com

发现 ping 不通

修改配置文件,加入以下内容

1
2
3
4
5
6
{
  "ipv6": true,
  "fixed-cidr-v6": "fd00::/80",
  "ip6tables": true,
  "experimental": true
}

重启 Docker,再次测试,发现可以 ping 通了

新加的配置项 ip6tables 是用来开启 IPv6 NAT 的,experimental 是用来开启 IPv6 NAT 的前提,不加这个配置项,ip6tables 会被忽略

如果是 docker-compose,先创建一个网络,并在 docker-compose.yml 中指定网络

1
docker network create --subnet=fd01::/80 --gateway=fd01::1  --ipv6 imciel-com
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
version: '3.7'
services:
  image: busybox
  command: ping -6 -c4 google.com
  networks:
    - imciel-com

networks:
  imciel-com:
    name: imciel-com

以上

Built with Hugo
主题 StackJimmy 设计