1這篇我研究6個小時,解決了大大小小的問題,也稍微搞清楚了docker的網路架構。
這次的任務不單單是要讓docker容器(container)中能直接用ip6來連線外,還要讓容器中能取得來源的ip6。
系統
# cat /etc/redhat-release
Rocky Linux release 9.0 (Blue Onyx)
# docker version
Client: Docker Engine - Community
Version: 20.10.21
Server: Docker Engine - Community
Engine:
Version: 20.10.21
# docker compose version
Docker Compose version v2.12.2
架構
外部網路 ==>
php(fd00:ffff:1::5/80 auto)
外部網路連到載體OS的ip6是Global Address;裡面的ip6是Unique Local Address (ULA)。
docker設定
啟動ip6路由
新增 /etc/docker/daemon.json [1][2]
"ipv6": true,
"fixed-cidr-v6": "fd00:ffff::/80",
"ip6tables": true,
"experimental": true
}
重啟docker後會看到 docker0 這個介面出現[2][3]。
後面二行如果沒有加的話,還是會通,只是會變成snat mode,加了這兩行變routing mode。如果出現錯誤,請參考下面錯誤排除[5]。
docker compose
新增一個網路 net6,並將nginx,php 加入此網路。
version: '3.8'
services:
nginx:
image: nginx:latest
ports:
- "80:80"
- "443:443"
networks:
- net6
php:
image: php:8.1-fpm-mysqli
ports:
- 9000
networks:
- net6
networks:
net6:
name: net6
enable_ipv6: true <== 一定要加
driver: bridge <== 可加可不加
ipam:
config:
- subnet: fd00:ffff:1::/80
gateway: fd00:ffff:1::1
- subnet: "172.16.163.0/24"
上面可以看到 net6 中的ip6有指定一個網路和gateway,ip4的subnet部分非必要。
容器中的ip6一直無法生效但是又找不到原因,後來意外發現networks還是使用 2.X的版本(請看下面測試),明明我指定3.8的版本…
重啟 docker compose 生效
測試
1. 查看網路介面,應該有 docker0
...
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
link/ether b6:c8:22:05:84:1c brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global noprefixroute docker0
valid_lft forever preferred_lft forever
inet6 fd00:ffff::1/80 scope global tentative
valid_lft forever preferred_lft forever
inet6 fe80::1/64 scope link tentative
valid_lft forever preferred_lft forever
2. 查看 docker net6
# docker inspect net6
[
{
"Name": "net6",
"Id": "7d229137b375fe741cf61800583930770a1a27ac48862e87d03e12ae87e1f080",
"Created": "2023-01-04T11:07:21.810957973+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": true,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.16.163.0/24"
},
{
"Subnet": "fd00:ffff:1::/80",
"Gateway": "fd00:ffff:1::1"
}
]
},
... 略 ...
"Containers": {
"5d50ad4e738ad6674a1943f34595fd0b40f7c4720e41c10e56e4662c93889292": {
"Name": "php",
"EndpointID": "253124353ab62132ae68246d01872eca68ecf9eb2d4c7b2868358aa4aa764355",
"MacAddress": "02:42:ac:10:a3:05",
"IPv4Address": "172.16.163.5/24",
"IPv6Address": "fd00:ffff:1::5/80"
},
"773a7dde22c25759fda04d416dd0ad7630cefc34420792c298f9f72813e8eef4": {
"Name": "nginx",
"EndpointID": "329e487d578db0e32e32fff219f8ee411e44d0b02453271922ef8dd9345dff8d",
"MacAddress": "02:42:ac:10:a3:03",
"IPv4Address": "172.16.163.3/24",
"IPv6Address": "fd00:ffff:1::3/80"
},
IPv6Address 的位址是自動產生的,每次都會不一樣。
ping6 看看該位址是否能順利取得。
3. 查看路由
大致上這樣,綠色的部分ok
::1 dev lo proto kernel metric 256 pref medium
2001:288:1234:2::/64 dev ens192 proto kernel metric 100 pref medium
fd00:ffff::/80 dev docker0 proto kernel metric 256 linkdown pref medium
fd00:ffff::/80 dev docker0 metric 1024 linkdown pref medium
fd00:ffff:1::/80 dev br-7d229137b375 proto kernel metric 256 pref medium
fe80::/64 dev docker0 proto kernel metric 256 linkdown pref medium
fe80::/64 dev br-7d229137b375 proto kernel metric 256 pref medium
fe80::/64 dev br-5c0b5382ef95 proto kernel metric 256 pref medium
fe80::/64 dev vethca3313c proto kernel metric 256 pref medium
fe80::/64 dev veth0917957 proto kernel metric 256 pref medium
fe80::/64 dev ens192 proto kernel metric 1024 pref medium
default via 2001:288:1234:2::ff dev ens192 proto static metric 100 pref medium
4. 網頁測試
index.php
phpinfo();
查看 REMOTE_ADDR 是不是外部的ip6 ?
錯誤排除
1. docker.service: Start request repeated too quickly.
/etc/docker/daemon.json 文件有問題,有非法字符?刪除多餘空格,ip6位址寫錯什麼的。
2. failed to start daemon: Error initializing network controller: Error creating default "bridge" network: Failed to program NAT chain: ZONE_CONFLICT: 'docker0' already bound to a zone
docker
interfaces: br-7d229137b375 br-5c0b5382ef95
public
interfaces: ens192 docker0
把 docker0 移到 docker ZONE 即可。
# firewall-cmd --permanent --zone=docker --change-interface=docker0
# firewall-cmd --reload
參考資料
[2] https://blog.iphoting.com/blog/2021/02/10/ipv6-docker-docker-compose-and-shorewall6-ip6tables/
[3] https://serverfault.com/questions/964533/how-to-setup-ipv6-with-docker-compose
[4] DOCKER官方 https://gdevillele.github.io/engine/userguide/networking/default_network/ipv6/
[5] https://blog.csdn.net/whatday/article/details/125398094