【问题标题】:How to assign IPv6 address with docker-compose如何使用 docker-compose 分配 IPv6 地址
【发布时间】:2017-01-31 15:30:44
【问题描述】:

我在 Ubuntu 16.04 上使用 docker 1.12.1 和 docker-compose 1.8.1。我正在尝试从 https://docs.docker.com/compose/compose-file/#ipv4-address-ipv6-address 获取 Compose 文件以运行。作为参考,我创建了docker-compose.yml,内容如下:

version: '2'

services:
  app:
    image: busybox
    command: ifconfig
    networks:
      app_net:
        ipv4_address: 172.16.238.10
        ipv6_address: 2001:3984:3989::10

networks:
  app_net:
    driver: bridge
    driver_opts:
      com.docker.network.enable_ipv6: "true"
    ipam:
      driver: default
      config:
      - subnet: 172.16.238.0/24
        gateway: 172.16.238.1
      - subnet: 2001:3984:3989::/64
        gateway: 2001:3984:3989::1

现在,运行 docker-compose up 产生

Creating network "tmp_app_net" with driver "bridge"
Creating tmp_app_1
Attaching to tmp_app_1
app_1  | eth0      Link encap:Ethernet  HWaddr 02:42:AC:10:EE:0A  
app_1  |           inet addr:172.16.238.10  Bcast:0.0.0.0  Mask:255.255.255.0
app_1  |           inet6 addr: fe80::42:acff:fe10:ee0a/64 Scope:Link
app_1  |           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
app_1  |           RX packets:4 errors:0 dropped:0 overruns:0 frame:0
app_1  |           TX packets:1 errors:0 dropped:0 overruns:0 carrier:0
app_1  |           collisions:0 txqueuelen:0 
app_1  |           RX bytes:520 (520.0 B)  TX bytes:90 (90.0 B)
app_1  | 
app_1  | lo        Link encap:Local Loopback  
app_1  |           inet addr:127.0.0.1  Mask:255.0.0.0
app_1  |           inet6 addr: ::1/128 Scope:Host
app_1  |           UP LOOPBACK RUNNING  MTU:65536  Metric:1
app_1  |           RX packets:0 errors:0 dropped:0 overruns:0 frame:0
app_1  |           TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
app_1  |           collisions:0 txqueuelen:1 
app_1  |           RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
app_1  | 
tmp_app_1 exited with code 0

未分配 IPv6 地址。

我已经试过了:

  1. 使用--ipv6 启动 docker 守护进程
  2. 使用--ipv6 --fixed-cidr-v6="2001:3984:3989::/64" 启动 docker 守护进程
    • 请注意,docker run -it busybox ifconfig 实际上在这里给了我一个 IPv6 地址(来自分配给默认 bridge 网络的 --fixed-cidr 子网)
  3. 使用我的实际 IPv6 子网而不是代码示例中的子网,并重复 2. 使用此子网

没有成功。有什么想法吗?

【问题讨论】:

    标签: docker docker-compose ipv6


    【解决方案1】:

    事实证明,这确实是一个 docker-compose bug,将在 1.9.0 中修复。

    同时,有一种解决方法是使用docker network 命令创建自定义网络:

    docker network create --subnet=172.16.2.0/24 --gateway=172.16.2.1 --ipv6 --subnet=<myV6Network/subnet> dockerbridge
    

    ...然后可以通过写入在docker-composed.yml 中使用

    networks:
      dockerbridge:
        external:
          name: dockerbridge
    

    【讨论】:

      【解决方案2】:

      是的。 Docker compose 支持 IPv6 协议,它被引入到 docker engine 1.5 以后。还有issue with latest compose file format 3.3 所以你可以使用 2.1 格式。 docker swarm 在高级网络配置方面仍然不够成熟,并且不支持 IPv6,因此它不包含在 3.3 fil 格式下。 这是文件的示例,

      docker-compose.yml

      version: ‘2.1’
      services:
        app:
          image: busybox
          command: ping www.google.com
          networks:
            app_net:
              ipv6_address: 2001:3200:3200::20
      networks:
        app_net:
          enable_ipv6: true
          driver: bridge
          ipam:
            driver: default
            config:
              - subnet: 2001:3200:3200::/64
                gateway: 2001:3200:3200::1
      

      此 docker compose 文件将基于子网 2001:3200:3200::/64 下的 IPv6 网络创建一个名为 testping_app_net 的新网络,并且容器应自动分配 IPv6 地址。

      让我们使用 docker-compose up 启动服务,看看服务是否通过 IPv6 协议进行通信:

      docker-compose up -d
      

      您可以使用验证每个容器的 IPv6 地址,

      docker exec -it 905 ip addr
      

      您将看到一个新容器获得 IPv6 地址 - 2001:3200:3200::20,因此它们能够相互通信。

      注意:如果要在主机上启用 IPv6,默认情况下使用 IPv4 地址,您需要将这两行添加到 daemon.json 下的 >/etc/docker 目录:

      {
          "ipv6": true,
          "fixed-cidr-v6": "2001:db8:1::/64"
      }
      

      并通过命令重启 docker 守护进程:

      $ sudo systemctl restart docker
      

      【讨论】:

        【解决方案3】:

        简答:

        docker-compose.yml 文件中添加 (3) 指令,(1) 到 daemon.json,然后重新构建容器并将 Docker 主机的 SLAAC 寻址接口放到 docker-compose 桥上,容器本身将收到 IPV6 SLAAC 地址。

        该解决方案被证明兼容:

        • docker-compose v. 2.1.1 和
        • docker-compose 文件格式 v. 3.9。

        如果您不知道如何实现上述目标,请阅读下面更长的答案。这实际上不是很困难或耗时。

        简介:

        (请随意跳过关于我要解决的问题的介绍性上下文)。

        像其他访问这个问题的人一样,我也遇到了 docker-compose 中的 IPv6 网络问题。据我所知,某些 IPV6 指令仅适用于更旧的 docker-compose 文件版本。这可能会对我猜的旧 docker-compose 文件版本不支持的新指令产生影响。而且有些解决方案不适用于 swarm。

        许多人似乎能够在他们的 docker-compose 配置中获得 IPV6 连接的唯一方法是使用一些沮丧的 Docker 用户编写的“IPV6 NAT”。顺便说一句,这不是批评:我们需要不会被打败的人,他们顽固地寻找解决问题/限制的方法。但是 IPv6 应该解决 NAT'ing 的问题 ;-)

        我想:一定有更简单的方法!

        还有……

        我的设置:

        如果您遇到困难,我将描述我的设置以进行比较分析:

        • 为 IPv6 SLAAC 寻址配置的 MikroTik 路由器连接到双栈 IPV4/V6 交换机。

        • 运行 64 位 Ubuntu 20.04 LTS 的 Raspberry Pi 4 通过 eth0 连接到交换机,从路由器获取其 IPv6 全球单播地址 (“GUA”)。

        • 使用的 Docker 版本 = Docker Engine Community v. 20.10.11

        • docker-compose = v. 2.1.1

        • docker-compose 文件格式 = v. 3.9

        docker-compose IPv6 配置:

        docker-compose.yml

        我的networks 部分:

        networks:
          my-custom-network:
            name: my-custom-network
            enable_ipv6: true
            ipam:
              driver: default
              config:
                - subnet: 192.168.XX.0/24
                  gateway: 192.168.xx.1
        

        请注意,唯一特定于 IPv6 的指令只是 enable_ipv6: true

        接下来,我的 docker-compose.yml 文件的相关部分包含我想要 IPV6 地址的容器的 services 部分中的其他 (2) 个 IPv6 特定指令:

        sysctls:
          - net.ipv6.conf.all.disable_ipv6=0
          - net.ipv6.conf.eth0.proxy_ndp=1
        

        显然是 YAML,请注意将该部分放在正确的前导空格中,否则当唯一的问题是指令的缩进时,它会产生误导性错误。

        /etc/docker/daemon.json

        我在这里只添加了 (1) 个 IPv6 特定指令:

          "ipv6": true, "fixed-cidr-v6": "2001:470:1d3f:8::/64",
        

        这一步是为我们的容器分配 IPv6 全局可路由 IPv6 地址所必需的。

        最后,在完成调整后,剪切一组新的容器(但不要启动它们):

        docker-compose build --no-cache
        

        Docker 主机网络配置:

        1. 在进行 IPv6 Docker 配置之前验证路由器的 IPv6 配置是否正确,方法是从您的 Docker 主机上使用 ping6 ping 一些东西:

          ping6 ipv6.google.com

        如果响应成功返回,则表明 Docker 主机和路由器都可以解析和路由 IPv6 数据包。现在问题已简化为解决容器 IPV6 问题。

        1. 由于 Pi 的 eth0 接口本身是 IPv6 寻址,并且与我们的路由器愉快地使用 IPv6,我们将把它加入到 docker-compose 网桥中:
        • 找到 docker-compose 网桥名称“br-series-of-random-chars”:

          ip addr list

        • 将 eth0 添加到网桥:

          ip link set dev eth0 master br-ckkde30ff0g

        注意:上述命令是 NON-Persistent- 它不会在重新启动后继续存在。添加 eth0 的过程可以完全自动化..

        • 检查 eth0 是否已加入:

          ip link | grep "master br-ckkde30ff0g"

        1. 启动你的容器:

          docker-compose start

        2. 现在将容器验证为 IPv6 GUA:

          docker exec -it containerName bash 然后:

          hostname -I

        您现在应该会看到一个 SLAAC 配置的 IPv6 GUA 地址。

        1. 在您的 IPv6 防火墙中戳一个洞以根据需要定制访问权限

        安全:

        谢天谢地,你不会看到:任何其他接收 IPv6 GUA 地址的容器。

        只有配置中包含上述 sysctls 指令的容器才会收到 SLAAC IPv6 地址 - 没有其他的。就我而言,我只想在 WordPress 站点前公开代理容器,而不是其他容器、网络服务器和后备数据库。所以只有代理可以通过 IPv6 访问。

        验证配置:

        以下站点是使用上述过程配置的 100% docker-compose 装置,因此可以证明此处概述的程序可以正常工作:

        http://[2001:470:1d3f:8:42:c0ff:fea8:1504]/
        

        请注意:我下周要更换 ISP,所以在配置新链接时可能会出现一些停机时间。

        您还可以使用 IPv6 测试站点验证容器的 IPv6 寻址的 IPV6 配置:

        https://ipv6-test.com/validate.php

        • 如果为裸域-domain.com设置了 AAAA DNS 记录,则在检查器中输入此作为 url。

        • 如果为子域 www 设置了 AAAA 记录,则在检查器中输入 www.domain.com

        结论:

        就是这样:只是 (3) 在docker-compose 中的 IPv6 特定指令,(1) 在 daemon.json 中,一些桥接和正确配置 IPv6 的路由器。完毕。并且不需要 NAT。

        同样,这不是一个完美或理想的解决方案,但它是解决 IPv6 连接问题的另一种方法。如果我在某个地方错过了一步,请给我留言。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-09-08
          • 2017-11-09
          • 2017-04-11
          相关资源
          最近更新 更多