草庐IT

启用Docker对ipv6的支持

Cloud-Future 2023-04-09 原文

我的环境:

  • OS: CentOS 7.9
  • Docker:20.10.7

1. 启用Docker守护进程对ipv6的支持

要想在Docker容器或者Swarm服务中使用ipv6,首先需要在Docker守护进程中启用对ipv6的支持,具体做法如下:

  1. 编辑docker守护进程的配置文件/etc/docker/daemon.json (若不存在需要手动创建该文件)

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

    ipv6设置为true,启用对ipv6的支持。
    fixed-cidr-v6,配置ipv6子网。
    ip6tables,启用ip6tables,docker会在ip6tables中配置docker网络相关的规则链。
    experimental,启用实验特性,ip6tables是docker的一个实验功能,所以需要设为true。

  2. 重载配置文件

     sudo systemctl reload docker && sudo systemctl restart docker
    

    现在你可以使用docker network create --ipv6 ... 创建一个支持ipv6的网络了。另外你也可以在启动容器时使用--ip6参数来使容器支持ipv6。

  3. 审查默认bridge网络

     sudo docker network inspect bridge
    


    可以看到已经配置成功!

接下来就可以在容器中使用ipv6了!

2. 在Docker容器中使用ipv6

注意:以下演示依赖于上一步的配置

2.1 创建一个容器

使用nginx做演示:
启动一个容器,此处并没有指定网络所以默认使用名为bridge的网络,该网络在上一步已经支持ipv6了!

docker run --name test -p 81:80 -d nginx:1.21.6

进入容器内部查看网阔配置:

$ docker exec -it test ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.156.10.2  netmask 255.255.255.0  broadcast 10.156.10.255
        inet6 fe80::42:aff:fe9c:a02  prefixlen 64  scopeid 0x20<link>
        inet6 2001:db8:1::242:a9c:a02  prefixlen 64  scopeid 0x0<global>
        ether 02:42:0a:9c:0a:02  txqueuelen 0  (Ethernet)
        RX packets 3923  bytes 9184337 (8.7 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 2836  bytes 192127 (187.6 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

容器内部已经分配了一个ipv6地址!

2.2 容器与宿主机通信

在上一步容器已经有一个ipv6地址了,但是如果宿主机没有一个合适的ipv6地址还是不能通过ipv6与宿主机通信。比如下面我用的宿主机网络配置:

$ ifconfig ens192
ens192: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.30.72  netmask 255.255.0.0  broadcast 192.168.255.255
        inet6 fe80::54f2:a4e2:f5cc:711a  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:c7:26:f5  txqueuelen 1000  (Ethernet)
        RX packets 38098236  bytes 6981689290 (6.5 GiB)
        RX errors 0  dropped 3567426  overruns 0  frame 0
        TX packets 953026  bytes 578286181 (551.4 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

尽管该接口有一个ipv6地址fe80::54f2:a4e2:f5cc:711a但是它是本地链路上的私有地址(fe80开头的地址属于私有地址)。私有地址是允许在本地链路上使用,且数据包不会跨链路转发。

所以,容器要想和宿主机通信,宿主机必须有一个非私有ipv6地址,如果默认没有就需要手动配置一个:
编辑网络接口配置文件/etc/sysconfig/network-scripts/ifcfg-ifName,例如我的测试宿主机网卡名称为ens192,那就编辑/etc/sysconfig/network-scripts/ifcfg-ens192:

TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=none
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=no
IPV6_DEFROUTE=yes
IPV6_PRIVACY=no
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
IPV6ADDR=2018::27
NAME=ens192
UUID=08b8bead-340c-4708-8656-2af2394a7c1c
DEVICE=ens192
ONBOOT=yes
IPADDR=192.168.30.72
PREFIX=16
GATEWAY=192.168.30.1
DNS1=223.5.5.5

保存,执行网络服务重启:

sudo systemctl restart network

查看网卡配置:

$ ifconfig ens192
ens192: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.30.72  netmask 255.255.0.0  broadcast 192.168.255.255
        inet6 2018::27  prefixlen 64  scopeid 0x0<global>
        inet6 fe80::54f2:a4e2:f5cc:711a  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:c7:26:f5  txqueuelen 1000  (Ethernet)
        RX packets 38106119  bytes 6982319769 (6.5 GiB)
        RX errors 0  dropped 3568059  overruns 0  frame 0
        TX packets 953451  bytes 578328655 (551.5 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

再次进行容器内ping宿主机:

$ sudo docker exec -it test ping6 2018::27
PING 2018::27(2018::27) 56 data bytes
64 bytes from 2018::27: icmp_seq=1 ttl=64 time=0.135 ms
64 bytes from 2018::27: icmp_seq=2 ttl=64 time=0.137 ms
64 bytes from 2018::27: icmp_seq=3 ttl=64 time=0.145 ms
64 bytes from 2018::27: icmp_seq=4 ttl=64 time=0.137 ms
64 bytes from 2018::27: icmp_seq=5 ttl=64 time=0.152 ms
^C
--- 2018::27 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4000ms
rtt min/avg/max/mdev = 0.135/0.141/0.152/0.006 ms

已经通了!

3. 使docker-compose 编排文件启动的服务支持ipv6

以下操作也须在docker引擎开启ipv6下进行。

3.1 对于版本2的编排文件

对于版本2的编排文件,可以直接在networks配置节点下启用ipv6,下面是个例子:

version: '2'
 #  其他services定义省略。。。 
networks:
  example:
    enable_ipv6: true
    driver: bridge
    driver_opts:
      com.docker.network.enable_ipv6: "true"
    ipam:
      config:
       - subnet: 172.23.0.0/16
       - subnet: "2607:f0d0:1002:51:4000::/66"

3.2 对于版本3的编排文件

对于版本3的编排文件,无法像上边那样直接在编排文件中配置网络并开启ipv6,需要按照下面的方式进行:
首先需要通过命令行创建一个网络并启用ipv6:

$ sudo docker network create -d bridge \
     --ipv6 --subnet 2001:db8:1::1/64 \
     --subnet 10.156.11.0/24 extnetwork

通过上面的命令创建了一个子网为2001:db8:1::1/64的名字为extnetwork的ipv6网络且支持ipv4。

编排文件:

version: '3'
services:
  app:
    image: app:7.16.1
    container_name: app
    restart: always
    privileged: true
    networks:
      - extnetwork 
  #省略其他服务。。。

networks:
  extnetwork:
    external: true

有关启用Docker对ipv6的支持的更多相关文章

  1. ruby-on-rails - 启用 Rack::Deflater 时 ETag 发生变化 - 2

    在启用Rack::Deflater来gzip我的响应主体时偶然发现了一些奇怪的东西。也许我遗漏了一些东西,但启用此功能后,响应被压缩,但是资源的ETag在每个请求上都会发生变化。这会强制应用程序每次都响应,而不是发送304。这在没有启用Rack::Deflater的情况下有效,我已经验证页面源没有改变。我正在运行一个使用thin作为Web服务器的Rails应用程序。Gemfile.lockhttps://gist.github.com/2510816有没有什么方法可以让我从Rack中间件获得更多的输出,这样我就可以看到发生了什么?提前致谢。 最佳答案

  2. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  3. ruby - 如何使用 readline 支持重新安装 ruby​​? - 2

    我已经按照https://github.com/wayneeseguin/rvm#installation上的说明通过RVM安装了Ruby.有关信息,我有所有文件(readline-5.2.tar.gz、readline-6.2.tar.gz、ruby-1.9.3-p327.tar.bz2、rubygems-1.8.24.tgz、wayneeseguin-rvm-stable.tgz和yaml-0.1.4.tar.gz)在~/.rvm/archives目录中,我不想在任何目录中重新下载它们方式。当我这样做时:sudo/usr/bin/apt-getinstallbuild-essent

  4. ruby-on-rails - "undefined method ` stub_request '"访问 RSpec 支持文件中的方法时 - 2

    我的Ruby-on-Rails项目中有以下文件结构,用于规范:/spec/msd/serviceservice_spec.rb/support/my_modulerequests_stubs.rb我的request_stubs.rb有:moduleMyModule::RequestsStubsmodule_functiondeflist_clientsurl="dummysite.com/clients"stub_request(:get,url).to_return(status:200,body:"clientsbody")endend在我的service_spec.rb我有:re

  5. ruby - Ruby 是否支持逐字字符串? - 2

    Ruby是否支持(找不到更好的词)非转义(逐字)字符串?就像在C#中一样:@"c:\ProgramFiles\"...或者在Tcl中:{c:\ProgramFiles\} 最佳答案 是的,您需要在字符串前加上%前缀,然后是描述其类型的单个字符。你想要的是%q{c:\programfiles\}。镐书很好地涵盖了这一点here,部分是通用分隔输入。 关于ruby-Ruby是否支持逐字字符串?,我们在StackOverflow上找到一个类似的问题: https:/

  6. ruby - 在 Ruby 1.8 中支持 Ruby 1.9 的哈希语法 - 2

    我正在编写一个Rubygem,在我的代码中使用{key:'value'}哈希语法。我的测试都在1.9.x中通过,但我(可以理解)在1.8.7中得到syntaxerror,unexpected':',expecting')'。是否有支持1.8.x的最佳实践?我是否需要使用我们的老friend=>重写代码,还是有更好的策略? 最佳答案 我认为你运气不好,如果你想支持1.8,那么你必须使用=>。像往常一样,我会提到在1.9的某些情况下您必须使用=>:如果键不是一个符号。请记住,任何对象(符号、字符串、类、float……)都可以是Ruby哈

  7. ruby-on-rails - 私有(private) gem 没有安装在 docker 中 - 2

    我正在尝试使用docker运行一个Rails应用程序。通过github的sshurl安装的gem很少,如下所示:Gemfilegem'swagger-docs',:git=>'git@github.com:xyz/swagger-docs.git',:branch=>'my_branch'我在docker中添加了keys,它能够克隆所需的repo并从git安装gem。DockerfileRUNmkdir-p/root/.sshCOPY./id_rsa/root/.ssh/id_rsaRUNchmod700/root/.ssh/id_rsaRUNssh-keygen-f/root/.ss

  8. ruby-on-rails - Rails 是否支持监听 UDP 套接字的简洁方式? - 2

    在Rails中,什么是集成更新模型某些元素的UDP监听过程的最佳方式(特别是它将向其中一个表添加行)。简单的答案似乎是在同一个进程中使用UDP套接字对象启动一个线程,但我什至不清楚我应该在哪里做适合Rails方式的事情。有没有一种巧妙的方法来开始收听UDP?具体来说,我希望能够编写一个UDPController并在每个数据报消息上调用一个特定的方法。理想情况下,我希望避免在UDP上使用HTTP(因为它会浪费一些在这种情况下非常宝贵的空间),但我完全控制消息格式,因此我可以为Rails提供它需要的任何信息。 最佳答案 Rails是一个

  9. ruby - 使用 Selenium WebDriver 启用/禁用 javascript - 2

    出于某种原因,我必须为Firefox禁用javascript(手动,我们按照提到的步骤执行http://support.mozilla.org/en-US/kb/javascript-settings-for-interactive-web-pages#w_enabling-and-disabling-javascript)。使用Ruby的SeleniumWebDriver如何实现这一点? 最佳答案 是的,这是可能的。而是另一种方式。您首先需要查看链接Selenium::WebDriver::Firefox::Profile#[]=

  10. ruby-on-rails - 将 Heroku 环境变量传输到 Docker 实例 - 2

    我在Heroku上构建了一个必须在Docker容器内运行的RoR应用程序。为此,我使用officialDockerfile.因为它在Heroku中很常见,所以我需要一些附加组件才能使这个应用程序完全运行。在生产中,变量DATABASE_URL在我的应用程序中可用。但是,如果我尝试其他一些使用环境变量(在我的例子中是Mailtrap)的加载项,变量不会在运行时复制到实例中。所以我的问题很简单:如何让docker实例在Heroku上执行时知道环境变量?您可能会问,我已经知道我们可以在docker-compose.yml中指定一个environment指令。我想避免这种情况,以便能够通过项目

随机推荐