[精讚] [會員登入]
386

[Docker] IPv6+nginx+php 讓docker中的容器支援ipv6,讀取到外部ipv6

docker中的容器要如何讀取到來源的ip6?這裡眉角很多。

分享此文連結 //n.sfs.tw/16037

分享連結 [Docker] IPv6+nginx+php 讓docker中的容器支援ipv6,讀取到外部ipv6@新精讚
(文章歡迎轉載,務必尊重版權註明連結來源)
2023-01-04 12:42:24 最後編修
2023-01-03 23:58:16 By 張○○
 

自動目錄

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

 

架構

 

外部網路 ==>

載體OS (2001:288:1234:2::2/64) ==>
docker0 (fd00:ffff::1/80) ==>
net6 (fd00:ffff:1::1/80) ==>
nginx (fd00:ffff:1::3/80 auto)
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部分非必要。

enable_ipv6: true 這個看文件說 3.0後就會出錯,所以我一開始沒加,後來發現不加的話,容器中的ip6就不生效了。
容器中的ip6一直無法生效但是又找不到原因,後來意外發現networks還是使用 2.X的版本(請看下面測試),明明我指定3.8的版本…

重啟 docker compose 生效

測試

1. 查看網路介面,應該有 docker0

# ip addr
...
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

# ip -6 route
::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

<?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

# firewall-cmd --get-active-zones
docker
  interfaces: br-7d229137b375 br-5c0b5382ef95
public
  interfaces: ens192 docker0

把 docker0 移到 docker ZONE 即可。

# firewall-cmd --permanent --zone=docker --change-interface=docker0

# firewall-cmd --reload

 

 

參考資料

[1] https://stackoverflow.com/questions/72049115/docker-compose-containers-cannot-access-internet-unless-on-host-network-ipv6-o

[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

[6] https://stackoverflow.com/questions/65213831/failed-to-start-daemon-error-initializing-network-controller-error-creating-de

 

 

END

你可能感興趣的文章

[Centos7] 安裝nodejs8+yarn 安裝nodejs 8+ yarn的過程記錄

Linux shell 的date表示法 linux下SHELL中的date表示法

[Rocky9] LetsEncrypt + nginx + docker 使用 certbot container 配合 nginx 來設製HTTPS.

DNS壓力測試工具queryperf 要怎麼知道我安裝的DNS是否能耐受的住網路上的攻擊或大量查詢,這裡有一個免費的工具 queryperf

[Rocky9] 負載平衡器Haproxy安裝及設定 負載平衡器Haproxy安裝及設定,這次的範例是透過本機的一個埠背後連到數台資料庫伺服器。

移除ssl 私鑰的密碼 現在用ssl產生私鑰會需要設定密碼,但是私鑰有密碼,啟動apache會失敗。

我有話要說

>>

限制:留言最高字數1000字。 限制:未登入訪客,每則留言間隔需超過10分鐘,每日最多5則留言。

訪客留言

[無留言]

隨機好文

[jQuery] 利用load()來達成ajax的寫法 jQuery中利用load()來達成ajax的寫法,也有人稱他是假的ajax,作法就是..

[HP DL380G7] 生效啟動第3,4片網卡/開啟或關閉內建的網卡 HP DL380G7 預設第3,4片網卡裝完系統後找不到,難道是壞了?要怎麼辦?

Linux shell 的date表示法 linux下SHELL中的date表示法

NETCRAFT發現你的網站及作業系統 NETCRAFT可以發現你的網站及作業系統

精讚的版面變化 ▓此文僅作為舊文的記錄▓ 這篇文章為了紀念改版完成而撰寫。 原本的部落格是民國97年的作品,那時還是用舊有的技術來寫,很