Overview#
Docker has supported IPv6 for quite some time, yet it remains disabled by default. This article documents enabling container IPv6 outbound capacity via NAT ULA on Debian 13. This method avoids complex routing broadcasts and mirrors the IPv4 experience almost identically.
Modifying Configuration#
Edit Docker daemon configuration file:
1
|
sudo vim /etc/docker/daemon.json
|
Add the following configuration:
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"
},
// Globally enable IPv6
"ipv6": true,
// Allocate ULA address block
"fixed-cidr-v6": "fd00:dead:beef::/64",
"experimental": true,
// Enable NAT translation (ip6tables)
"ip6tables": true,
// Private address pools
"default-address-pools": [
{
"base": "172.17.0.0/16",
"size": 24
},
{
"base": "fd00:dead:beef:100::/80",
"size": 112
}
]
}
|
Restart Docker for settings to take effect:
1
|
sudo systemctl restart docker
|
Usage#
Verify the container now possesses IPv6 outbound capability:
1
2
3
|
# HTTP/2 200
sudo docker run --rm curlimages/curl curl -s -I -6 https://blog.zsh.moe
|
For Compose orchestrated container services, implementation is similarly straightforward (e.g., 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
# Enable IPv6 forwarding
- net.ipv6.conf.all.forwarding=1
# Accept Docker bridge routing advertisements
- 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
# Explicitly enable IPv6 support
enable_ipv6: true
|
Start service:
1
|
sudo docker compose up -d
|
Inspect container-internal network interfaces to verify successful private IP capture:
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
# Output Example
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
# IP allocated from the IPv6 ULA pool
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
|
Test Warp IPv6 proxy outbound capacity:
1
2
3
|
# HTTP/2 200
sudo docker exec warp curl -x socks5h://[::1]:1080 -6 https://blog.zsh.moe -v
|
Conclusion#
We predefined a massive private address pool; Docker automatically allocates private IPv6s, transiting via host NAT outbound. Subnet division overheads bypassed, granting containers seamless dual-stack outbound abilities.
References: