现在 ipv6 用的越来越多,很多时候我们需要让容器通过 ipv6 访问服务,或者让外部通过 ipv6 访问我们的容器。这里记录下给容器配置 ipv6 网络的方式。

前置条件

如果需要通过容器访问外部的 ipv6 服务,那需要先保证宿主机上是有 ipv6 地址的。否则配置了 ipv6 也只是内网之间可以通过子网互通。

配置方式

检查宿主机是否开启 ipv6 转发

执行下面的命令

sysctl net.ipv6.conf.all.forwarding

如果返会是 1,说明已经开启了,否则按下面的方式开启。

  • 临时生效(重启消失)
    sudo sysctl -w net.ipv6.conf.all.forwarding=1
    
  • 永久生效(重启不失效)
    你需要编辑系统配置文件 /etc/sysctl.conf,添加或取消注释以下行:
net.ipv6.conf.all.forwarding=1
net.ipv6.conf.default.forwarding=1

然后执行以下命令刷新配置:

sudo sysctl -p

这个配置支持 0 和 1。
0(默认):主机模式(Host)。收到不是发给自己的数据包,直接丢弃。
1(开启):路由模式(Router)。收到数据包后,会查看自己的“地图”(路由表),发现是给容器的,就帮它转交过去。当容器想要访问 google.com 时,数据包首先到达宿主机的虚拟网卡。

如果没有开启转发,宿主机会认为这个数据包“不合法”,因为它不是宿主机自己产生的,从而导致容器断网。

因为 ipv6 和 ipv4 是独立的配置,所以这里新配置 ipv6 时需要检查这个参数。

docker 开启 ipv6 支持

docker 默认是没有开启 ipv6 的,这里需要现配置 docker,让它支持 ipv6。
修改 /etc/docker/daemon.json,添加下面的内容。

{
  "ipv6": true,
  "fixed-cidr-v6": "fd00::/64",
  "ip6tables": true,
  "dns": [
    "8.8.8.8",
    "2001:4860:4860::8888"
    "223.6.6.6"
    "223.5.5.5"
    "2400:3200::1"
    "2001:4860:4860::8888"
  ]
}

这里 DNS 可以根据自己的需要调整,我的服务器在国内的比较多,所以大量用了阿里云的 DNS。

docker compose 里配置网络

如果是使用的 docker compose,需要独立的配置网络和 DNS 部分。

version: '3'
services:
  my_app:
    image: alpine
    command: sleep infinity
    # 在这里指定 DNS
    dns:
      - 2400:3200::1        # 阿里 IPv6 DNS
      - 223.5.5.5           # 阿里 IPv4 DNS
      - 2001:4860:4860::8888 # Google IPv6 DNS

networks:
  default:
    enable_ipv6: true
    ipam:
      config:
        - subnet: "fd00:1::/64" # 确保网络也开启了 IPv6

下面的 networks 部分是必须配置的,显示的开启 ipv6。然后 subnet 部分每个容器需要分配不一样的段,要不然会冲突。

检查容器是否拿到了 ipv6

# 查看容器的网络详情
docker inspect <容器名或ID> | grep -i "IPv6Address"
  • 如果显示 "IPv6Address": "",说明没配置成功。
  • 如果显示 "IPv6Address": "fd00:db8:1::...",说明容器已经拥有了“二等公民”身份,具备了 IPv6 通讯能力