概述

Docker 对 IPv6 的支持已经很久了,但默认仍未启用。本文记录在 Debian 13 下通过 NAT ULA,让容器获得 IPv6 出网能力。这种方式无需配置复杂的路由广播,使用体验与 IPv4 几乎完全一致。

修改配置

编辑 Docker 守护进程配置文件

1
sudo vim /etc/docker/daemon.json

写入以下配置:

 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
42
43
44
45
46
47
48
49
{

  "log-driver": "json-file",

  "log-opts": {

    "max-size": "20m",

    "max-file": "3"

  },

  // 全局启用 IPv6

  "ipv6": true,

  // 分配 ULA 地址块

  "fixed-cidr-v6": "fd00:dead:beef::/64",

  "experimental": true,

  // 启用 NAT 转换

  "ip6tables": true,

  // 私有地址池

  "default-address-pools": [

    {

      "base": "172.17.0.0/16",

      "size": 24

    },

    {

      "base": "fd00:dead:beef:100::/80",

      "size": 112

    }

  ]

}

重启 Docker 服务使配置生效:

1
sudo systemctl restart docker

使用

验证容器现在是否具有 IPv6 出网能力

1
2
3
# HTTP/2 200

sudo docker run --rm curlimages/curl curl -s -I -6 https://blog.zsh.moe

对于 Compose 编排的容器服务,使用也很简单,以 Warp Docker 为例:

 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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
services:

  warp:

    image: caomingjun/warp:slim-latest

    container_name: warp

    restart: unless-stopped

    networks:

      - warp-tunnel

    device_cgroup_rules:

      - 'c 10:200 rwm'

    environment:

      - WARP_SLEEP=2

      - GOST_ARGS=-L socks5://:1080?udp=true -L http://:1081

    cap_add:

      - MKNOD

      - AUDIT_WRITE

      - NET_ADMIN

    sysctls:

      - net.ipv6.conf.all.disable_ipv6=0

      - net.ipv4.conf.all.src_valid_mark=1

      # 开启 IPv6 转发

      - net.ipv6.conf.all.forwarding=1

      # 接受 Docker 网桥路由公告

      - net.ipv6.conf.all.accept_ra=2

      - net.ipv4.ip_forward=1

    volumes:

      - ./data:/var/lib/cloudflare-warp

networks:

  warp-tunnel:

    name: warp-tunnel

    driver: bridge

    # 显式指定启用 IPv6 支持

    enable_ipv6: true

启动服务

1
sudo docker compose up -d

检查容器内网络接口,可以看到已成功获取私有地址

 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
sudo docker exec warp ip -6 addr show

# 输出示例

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 state UNKNOWN qlen 1000

    inet6 ::1/128 scope host

       valid_lft forever preferred_lft forever

2: eth0@if60: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP

    # IPv6 ULA 池划分的 IP

    inet6 fd00:dead:beef:100::2/112 scope global nodad

       valid_lft forever preferred_lft forever

    inet6 fe80::3cc7:aaff:fed1:1680/64 scope link

       valid_lft forever preferred_lft forever

3: CloudflareWARP: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1280 state UNKNOWN qlen 500

    inet6 2606:4700:cf1:1000::3/128 scope global

       valid_lft forever preferred_lft forever

    inet6 fe80::6594:3a07:3299:4dbe/64 scope link stable-privacy

       valid_lft forever preferred_lft forever

测试 Warp IPv6 代理的出网能力

1
2
3
# HTTP/2 200

sudo docker exec warp curl -x socks5h://[::1]:1080 -6 https://blog.zsh.moe -v

结论

我们预先定义了一个巨大的私有地址池,Docker 会自动给容器分配私有 IPv6,再经过宿主机 NAT 出网。无需手动划分子网,即可赋予容器无感知的双栈出网能力。

参考资料: