2-6-1-Docker网络管理

熊 0 阅读 容器

1. 容器间互联

即在同一个宿主机上的容器之间可以通过自定义的容器名称相互访问 , 比如一个业务前端静态页面是使用nginx , 动态页面使用的是tomcat由于容器在启动的时候其内部IP地址是DHCP随机分配的 , 所以如果通过内部访问的话 , 自定义名称是相对比较固定的 , 因此比较适用于此场景。

1.1 部署说明

  1. 先创建第一个tomcat容器 , 后续需要将nginx进行转发到此tomcat服务上

    [root@centos-7 ~]# docker run -it -d  --name tomcat1 tomcat-app1:v1
    dd097a9fd8baaa2da451c279bd9a008c3b7ec36c6cf4a032aa40e697aec549f7

    进入到tomcat服务里 , 查看tomcat的hosts文件

    [root@centos-7 ~]# docker exec -it tomcat1 bash
    [root@dd097a9fd8ba /]# cat /etc/hosts
    127.0.0.1   localhost
    ::1 localhost ip6-localhost ip6-loopback
    fe00::0 ip6-localnet
    ff00::0 ip6-mcastprefix
    ff02::1 ip6-allnodes
    ff02::2 ip6-allrouters
    172.17.0.3  dd097a9fd8ba  #tomcat的hosts文件解析
    1.2.1.3 www.google.net
  2. 开启一个nginx容器 , 并将tomcat容器关联起来,启动nginx服务。

    [root@centos-7 ~]# docker run -it -d --name nginx-web1 -p 80:80  --link tomcat1 nginx:v1
    24549e8fac8fade868004fe6a5c0bc25f04abc08e82f1acffc8c1fcb47e6df65
  3. 进入nginx服务 , 然后看nginx的hosts文件

    [root@centos-7 ~]# docker exec -it nginx-web2 bash
    [root@1e2556622e7b /]# cat /etc/hosts
    127.0.0.1   localhost
    ::1 localhost ip6-localhost ip6-loopback
    fe00::0 ip6-localnet
    ff00::0 ip6-mcastprefix
    ff02::1 ip6-allnodes
    ff02::2 ip6-allrouters
    172.17.0.3  tomcat1 dd097a9fd8ba  #可以看到已经将tomcat的host文件关联过来
    172.17.0.2  1e2556622e7b
  4. 进入到nginx配置服务器 , 然后修改nginx的配置文件 , 进行转发的tomcat容器部分

    [root@centos-7 ~]# docker exec -it nginx-web2 bash
    [root@f53f3ba8b1ad /]# vim /etc/nginx/nginx.conf  #修改nginx服务
        upstream tomcat  {   #http段进行修改
            server tomcat:8080; #转发到tomcat服务的IP地址和端口 , 直接转发域名 , 关联的tomcat服务器的名称不变 , 就会一直转发到tomcat服务器上
        }
     
      
            location /app1 {    # server段进行修改
            proxy_pass http://tomcat;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-FOR $proxy_add_x_forwarded_for;
            proxy_set_header X-Real-IP $remote_addr;
            }
     
    [root@f53f3ba8b1ad /]# nginx -t  # 测试语法
    [root@f53f3ba8b1ad /]# nginx -s reload  #重新加载nginx

    upstream段转发hosts域名 , link链接tomcat的名称 , 就算tomcat容器删除 , IP地址变化之后也没事 , 只需要重新进行link到同一个名称即可 , 这样就不需要修改nginx服务器内部配置文件 , 依然可以访问页面。

    此时访问宿主机的IP地址下的app1目录 , 就会访问到网页 :

    1769223-20200117103531720-1749089755

1.2 别名配置

上一步骤中 , 自定义的容器名称可能后期会发生变化 , 那么一旦名称发生变化 , 程序之间也要随之发生变化 , 比如程序通过容器名称进行服务调用 , 但是容器名称发生变化之后再使用之前的名称肯定是无法成功调用 , 每次都进行更改的话又比较麻烦 , 因此可以使用自定义别名的方式解决 , 即容器名称可以随意更改 , 只要不更改别名即可 , 具体如下 :

命令格式 :

docker run -d -name 新容器名称 --link 目标容器名称:自定义的名称 -p 本地端口:容器端口 镜像名称 shell 命令
  1. 重新创建一个tomcat容器 , 并启动。

    [root@centos-7 src]# docker run -it -d --name tomcat2 tomcat-app1:v1
  2. 将nginx容器与tomcat容器关联 , 并起一个容器别名,别名为tomcat.google.com

    [root@centos-7 ~]# docker run -it -d --name nginx-web3 -p 82:80  --link tomcat2:tomcat.google.com nginx:v1
  3. 进入nginx容器内 , 修改nginx配置文件

    [root@centos-7 ~]# docker exec -it nginx-web4 bash
    [root@faf64ae3e99b /]# vim /etc/nginx/nginx.conf      
         location /app1 {
               proxy_pass http://tomcat.google.com:8080; #直接监听别名解析
            }
     
    [root@faf64ae3e99b /]# nginx -t
    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful
    [root@faf64ae3e99b /]# nginx -s reload

测试页面 , 此时容器启动nginx监听的是82端口 , 因此需要82端口进行访问 :

1769223-20200117110538144-331540776

2. 网络模式

安装Docker时 , 它会自动创建三个网络 , bridge ( 创建容器默认连接到此网络 ) 、 none 、host

网络模式

简介

Host

容器将不会虚拟出自己的网卡 , 配置自己的IP等 , 而是使用宿主机的IP和端口。

Bridge

此模式会为每一个容器分配、设置IP等 , 并将容器连接到一个docker0虚拟网桥 , 通过docker0网桥以及Iptables nat表配置与宿主机通信。

None

该模式关闭了容器的网络功能。

Container

创建的容器不会创建自己的网卡 , 配置自己的IP , 而是和一个指定的容器共享IP、端口范围。

自定义网络

略

2.1 host网络模式

Host模式 , 使用参数--network host指定 , Host模式不支持端口映射 , 且容器无法启动。

启动的容器如果指定了使用host模式 , 那么新创建的容器不会创建自己的虚拟网卡 ( Network Namespace ) , 而是直接使用宿主机的网卡和IP地址 ( Network Namespace ) , 因此在容器里面查看到的IP信息就是宿主机的信息 , 访问容器的时候直接使用宿主机IP+容器端口即可 , 不过容器的其他资源们文件系统、系统进程等还是和宿主机必须保持隔离。此模式的网络性能最高 , 但是各容器之间端口不能相同 , 适用于运行容器端口比较固定的业务。

[root@centos-7 ~]# docker run -it -d  --name nginx-net-host --network host nginx:v1  # 打开指定host模式的容器
ac4e0be49a668d19935d9158e7e6a1c81c7afeac0d3dde88349979ab26e311dc
[root@centos-7 ~]# docker exec -it nginx-net-host bash # 进入到容器中
[root@centos-7 /]# ip a  #查看此host容器模式的IP地址 , 就是使用的是宿主机的IP地址
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:59:4a:1d brd ff:ff:ff:ff:ff:ff
    inet 192.168.7.100/24 brd 192.168.7.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe59:4a1d/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:a6:2c:bb:07 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:a6ff:fe2c:bb07/64 scope link
       valid_lft forever preferred_lft forever

2.2 None网络模式

使用none模式 , Docker容器拥有自己的Network Namespace , 但是 , 并不为Docker容器进行任何网络配置。也就是说 , 这个Docker容器没有网卡、IP、路由等信息 , 只有lo网络接口。需要我们自己为Docker容器添加网卡、配置IP等。

不参与网络通信 , 运行于此类容器中的进程仅能访问本地回环接口;仅适用于进程无须网络通信的场景中 , 例如 : 备份、进程诊断及各种离线任务等 , 此模式极少使用。

[root@centos-7 ~]# docker run -it -d --name nginx-net-host1 --network none nginx:v1  # 创建none网络模式
dd00a68d3853602902aae3b08f57c06827b649f764f951a60bc7e4c2298a0ea4
[root@centos-7 ~]# docker exec -it nginx-net-host1 bash
[root@dd00a68d3853 /]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
[root@dd00a68d3853 /]# ifconfig
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

2.3 Container网络模式(联盟式网络)

这个模式指定新创建的容器和已经存在的一个容器共享一个Network Namespace , 而不是和宿主机共享。新创建的容器不会创建自己的网卡 , 配置自己的IP , 而是和一个指定的容器共享IP、端口范围等。同样 , 两个容器除了网络方面 , 其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过lo网卡设备通信。

1769223-20200117130138486-1913672051
  1. 在一个终端 , 使用bridge网络模式启动容器tomcat1

    [root@centos-7 ~]# docker run -it --name tomcat1 --network bridge  -d tomcat-app1:v1
    10753fcfcd45b06eac55badca2166dcca5c76e26260d99bfa945f68ae8a50454
    [root@centos-7 ~]# docker exec -it tomcat1 bash
    [root@10753fcfcd45 /]# ip a  #查看此时的IP地址是172.17.0.2
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
    50: eth0@if51: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
        link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
        inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
           valid_lft forever preferred_lft forever
  2. 在另一个终端使用Container网络模式创建容器tomcat2 

    [root@centos-7 ~]# docker run -it -d -name tomcat2 --network container:tomcat1 tomcat-app1:v1  # 创建tomcat2容器
    [root@centos-7 ~]# docker exec -it tomcat2 bash  #进入到tomcat2
    [root@10753fcfcd45 /]# ip a   # 查看IP地址 , 此时的IP地址就和桥接模式的IP地址一致
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
    50: eth0@if51: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
        link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
        inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
           valid_lft forever preferred_lft forever

2.4 Bridge网络模式

当Docker进程启动时 , 会在主机上创建一个名为docker0的虚拟网桥 , 此主机上启动的Docker容器会连接到这个虚拟网桥上 , 所以有默认地址172.17.0.0/16的地址。虚拟网桥的工作方式和物理交换机类似 , 这样主机上的所有容器就通过交换机连在了一个二层网络中。

从docker0子网中分配一个IP给容器使用 , 并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备 , Docker将veth pair设备的一端放在新创建的容器中 , 并命名为eth0 ( 容器的网卡 ) , 另一端放在主机中 , 以ethxxx这样类似的名字命名 , 并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看。类似于vmware桥接模式

1769223-20200117130441295-511531084
[root@centos-7 ~]# brctl show
bridge name bridge id       STP enabled interfaces
docker0     8000.0242a62cbb07   no      veth4f25042<br>

bridge模式是docker的默认网络模式 , 不写--network参数 , 就是bridge模式。

[root@docker~]#docker run -it --name centos  --rm  centos:centos7.7.1908 /bin/sh # 默认的桥接模式

使用docker run 时 , docker实际是在iptables做了DNAT规则 , 实现端口转发功能 , 可以使用iptables -t nat -vnL查看 :

[root@centos-7 ~]# iptables -t nat -vnL
Chain PREROUTING (policy ACCEPT 31 packets, 5027 bytes)
 pkts bytes target     prot opt in     out     source               destination        
   31  1588 DOCKER     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL
 
Chain INPUT (policy ACCEPT 31 packets, 5027 bytes)
 pkts bytes target     prot opt in     out     source               destination        
 
Chain OUTPUT (policy ACCEPT 69 packets, 4024 bytes)
 pkts bytes target     prot opt in     out     source               destination        
    0     0 DOCKER     all  --  *      *       0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL
 
Chain POSTROUTING (policy ACCEPT 69 packets, 4024 bytes)
 pkts bytes target     prot opt in     out     source               destination        
  233 14471 MASQUERADE  all  --  *      !docker0  172.17.0.0/16        0.0.0.0/0          
 
Chain DOCKER (2 references)
 pkts bytes target     prot opt in     out     source               destination        
    0     0 RETURN     all  --  docker0 *       0.0.0.0/0            0.0.0.0/0 

3. docker网络命令汇总

3.1 查看网络

查看已经建立的网络对象

  • 语法 : docker network ls [OPTIONS]

  • 常用参数

    • -f ,--filter filter : 过滤条件(如 'driver=bridge’)

    • --no-trunc : 不要截断输出

    • -q,--quiet : 仅显示网络ID

    [root@harbor ubuntu]# docker network ls --no-trunc
    NETWORK ID                                                         NAME            DRIVER    SCOPE
    5a8c0e425060034646a84faa36b533d457fd60f0b234623d4afe7fab2b9c0fcb   bridge          bridge    local
    aba08dee359d9d58feaa8f0c87a032524de1856a584eec1a9b8d87f47b52eba7   harbor_harbor   bridge    local
    98eaf673ed1f3cb41562b42b033432521fda3fd8022734d1c8e603021391e920   host            host      local
    9bea05bfbf3ed3864c83e1ac7aff53d6ed18416213951bade875aa01898da196   none            null      local
    [root@harbor ubuntu]# docker network ls 
    NETWORK ID     NAME            DRIVER    SCOPE
    5a8c0e425060   bridge          bridge    local
    aba08dee359d   harbor_harbor   bridge    local
    98eaf673ed1f   host            host      local
    9bea05bfbf3e   none            null      local
    [root@harbor ubuntu]# docker network ls -q
    5a8c0e425060
    aba08dee359d
    98eaf673ed1f
    9bea05bfbf3e
    [root@harbor ubuntu]# docker network ls -f 'driver=host'
    NETWORK ID     NAME      DRIVER    SCOPE
    98eaf673ed1f   host      host      local

3.2 创建网络

创建新的网络对象

  • 语法 : docker network create [OPTIONS] NETWORK

  • OPTIONS

    • --driver string : 指定网络的驱动(默认 "bridge")

    • --subnet strings : 指定子网网段(如192.168.0.0/16、172.88.0.0/24)

    • --ip-range strings : 执行容器的IP范围,格式同subnet参数

    • --gateway strings : 子网的IPv4 or IPv6网关,如(192.168.0.1)

3.3 网络删除

删除一个或多个网络

  • 语法 : docker network rm NETWORK [NETWORK...]

3.4 查看网络详细信息

查看一个或多个网络的详细信息

  • 语法

    docker network inspect [OPTIONS] NETWORK [NETWORK...]
    
    docker inspect [OPTIONS] NETWORK [NETWORK...]
  • 常见参数

    • -f,--format string : 根据format输出结果

3.5 网络连接与断开

  • 语法

    docker network connect [OPTIONS] NETWORK CONTAINER 
    
    docker network disconnect [OPTIONS] NETWORK CONTAINER
  • 常见参数

    • --force : 强制断开连接(用于disconnect)

3.6 容器设置固定IP

docker network create -d bridge --subnet=172.172.0.0/24  --gateway 172.172.0.1 network 172.172.0.0/24: 24代表子码掩码是255.255.255.0 172.172.0.0/16: 16 代表子码掩码

docker network ls

docker run -itd --name nginx3 -p 80:80 --net network --ip 172.172.0.10 nginx:1.19.3-alpine

--net mynetwork:选择存在的网络

--ip 172.172.0.10:给nginx分配固定的IP地址

docker network inspect network

docker stop nginx3

docker start nginx3

docker network inspect network

4. Docker跨主机(不同网段)互联之简单实现

A主机 : 10.20.0.1/16

B主机 : 10.10.0.1/16

  • 自定义A主机修改Docker0地址

    1. 修改A主机的docker配置文件 , 指定docker0容器的IP地址 , 在定义docker0的IP地址时 , 一定要先定义IP , 后启动docker里边的容器 , 否则会重启docker会很慢。

      [root@centos7-2 ~]# vim /lib/systemd/system/docker.service
      ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock  --bip 10.20.0.1/16
       
      [root@centos7-2 ~]# systemctl daemon-reload
      [root@centos7-2 ~]# systemctl restart docker

      第二种方法 : 也可以在配置文件中添加bip :指定IP地址 , 在定义docker0的IP地址时 , 一定要先定义 , 后再启动docker里边的服务。

      [root@docker~]#cat /etc/docker/daemon.json
      {
        "registry-mirrors": ["https://kganztio.mirror.aliyuncs.com"],  # 加速器后面的逗号不能少
        "bip": "10.20.0.1/16"  # 指定要修改的IP地址 , 最后一行不需要以逗号结尾。
      }
      [root@docker ~]# systemctl restart docker
    2. 查看此时修改后的docker0的IP地址 , 此时就是修改后的IP地址

      1769223-20200117143838454-1206719967
  • 自定义B主机修改Docker0地址

    1. 修改B主机的docker地址 , 指定一个地址10.10.0.1/16

      [root@centos7 ~]# vim  /lib/systemd/system/docker.service
      ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock  --insecure-registry 192.168.7.103 --insecure-registry 192.168.7
      .102    --bip=10.10.0.1/16
       
      [root@centos7 ~]# systemctl daemon-reload
      [root@centos7 ~]# systemctl restart docker
    2. 查看修改后的IP地址

      1769223-20200117144154619-1556920216
  • 在两个宿主机分别开启一个容器

    1. A主机开启一个容器

      [root@centos7-2 ~]# docker run -it -d ubuntu 
      64a7e577cfbe1bad77c100794601fd8773a9ec8f3d63322af47e4f1bf6259e09
    2. B主机开启一个容器

      [root@centos7 ~]# docker run -it -d ubuntu
      eb87c3b52a22e0835397d27be1cdbf38ddca6588f956049d06aa5b650ce7f439
  • 添加静态路由

    1. 在A主机添加B主机的IP地址段和B主机的宿主机IP地址 , 并添加一个防火墙规则

      [root@centos7-2 ~]# ip route add 10.10.0.0/16 via 192.168.194.130
      [root@centos7-2 ~]#  iptables -A FORWARD -s 192.168.194.0/24 -j ACCEPT #允许此IP地址段的都可以访问
      [root@centos7-2 ~]# ip a
      1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
          link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
          inet 127.0.0.1/8 scope host lo
             valid_lft forever preferred_lft forever
          inet6 ::1/128 scope host 
             valid_lft forever preferred_lft forever
      2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
          link/ether 00:0c:29:f0:11:49 brd ff:ff:ff:ff:ff:ff
          inet 192.168.194.146/24 brd 192.168.194.255 scope global noprefixroute dynamic ens33
             valid_lft 1254sec preferred_lft 1254sec
          inet6 fe80::a165:fb01:7c53:3452/64 scope link noprefixroute 
             valid_lft forever preferred_lft forever
      4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
          link/ether 02:42:30:fb:53:b9 brd ff:ff:ff:ff:ff:ff
          inet 10.20.0.1/16 brd 10.20.255.255 scope global docker0
             valid_lft forever preferred_lft forever
          inet6 fe80::42:30ff:fefb:53b9/64 scope link 
             valid_lft forever preferred_lft forever
      74: vethdc7db42@if73: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
          link/ether ce:50:12:43:4a:5c brd ff:ff:ff:ff:ff:ff link-netnsid 0
          inet6 fe80::cc50:12ff:fe43:4a5c/64 scope link 
             valid_lft forever preferred_lft forever
      [root@centos7-2 ~]# ip r
      default via 192.168.194.2 dev ens33 proto dhcp metric 100 
      10.10.0.0/16 via 192.168.194.130 dev ens33 
      10.20.0.0/16 dev docker0 proto kernel scope link src 10.20.0.1 
      192.168.194.0/24 dev ens33 proto kernel scope link src 192.168.194.146 metric 100 
    2. 在B主机添加A主机的IP地址段和A主机的宿主机IP地址 , 并添加防火墙规则

      [root@centos7 ~]# ip r 
      default via 192.168.194.2 dev ens33 proto dhcp metric 100 
      10.10.0.0/16 dev docker0 proto kernel scope link src 10.10.0.1 
      192.168.194.0/24 dev ens33 proto kernel scope link src 192.168.194.130 metric 100 
      [root@centos7 ~]# ip a
      1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
          link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
          inet 127.0.0.1/8 scope host lo
             valid_lft forever preferred_lft forever
          inet6 ::1/128 scope host 
             valid_lft forever preferred_lft forever
      2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
          link/ether 00:0c:29:44:5c:5d brd ff:ff:ff:ff:ff:ff
          inet 192.168.194.130/24 brd 192.168.194.255 scope global noprefixroute dynamic ens33
             valid_lft 1525sec preferred_lft 1525sec
          inet6 fe80::a564:21d6:21e3:7e9c/64 scope link noprefixroute 
             valid_lft forever preferred_lft forever
      3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
          link/ether 02:42:9d:64:73:e7 brd ff:ff:ff:ff:ff:ff
          inet 10.10.0.1/16 brd 10.10.255.255 scope global docker0
             valid_lft forever preferred_lft forever
          inet6 fe80::42:9dff:fe64:73e7/64 scope link 
             valid_lft forever preferred_lft forever
      811: veth751dd86@if810: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
          link/ether c6:09:b0:df:8d:60 brd ff:ff:ff:ff:ff:ff link-netnsid 0
          inet6 fe80::c409:b0ff:fedf:8d60/64 scope link 
             valid_lft forever preferred_lft forever
      [root@centos7 ~]# ip route add 10.20.0.0/16 via 192.168.194.146
      [root@centos7 ~]# ip r
      default via 192.168.194.2 dev ens33 proto dhcp metric 100 
      10.10.0.0/16 dev docker0 proto kernel scope link src 10.10.0.1 
      10.20.0.0/16 via 192.168.194.146 dev ens33 
      192.168.194.0/24 dev ens33 proto kernel scope link src 192.168.194.130 metric 100 
      
      [root@centos7 ~]# iptables -A FORWARD -s 192.168.194.0/24 -j ACCEPT #允许此IP地址段的都可以访问
    3. 进入A主机开启的容器内部 , 然后ping测试B主机是否能够ping通

      [root@centos7-2 ~]# docker exec -it 64a7e577cfbe bash
      
      root@64a7e577cfbe:/# apt update
      root@64a7e577cfbe:/# apt install iptuils-ping 
      root@64a7e577cfbe:/# ping 10.10.0.1   
      PING 10.10.0.1 (10.10.0.1) 56(84) bytes of data.
      64 bytes from 10.10.0.1: icmp_seq=1 ttl=63 time=38.1 ms
    4. 此时B主机ping A主机也可以通

      [root@centos7 ~]# docker exec -it eb87c3b52a22 bash
      root@eb87c3b52a22:/# ping 10.20.0.2
      PING 10.20.0.2 (10.20.0.2) 56(84) bytes of data.
      64 bytes from 10.20.0.2: icmp_seq=1 ttl=62 time=0.790 ms
      64 bytes from 10.20.0.2: icmp_seq=2 ttl=62 time=0.347 ms

5. 自定义docker容器IP

  1. 创建一个网络名称为 : linux-net

    [root@centos7 ~]# docker network create -d bridge  --subnet 172.27.0.0/21  --gateway 172.27.0.1 linux-net
    81de3b1eaba16b4007d1c1ae300cb3bd6f2b0cf5b6f2b43265055c2f3edd2e81

    查看创建成功的网络信息 , 此时可以看到linux-net就是自己创建的网络

    [root@centos7 ~]# docker network ls
    NETWORK ID     NAME        DRIVER    SCOPE
    901f56044a09   bridge      bridge    local
    98eaf673ed1f   host        host      local
    81de3b1eaba1   linux-net   bridge    local ## 可以看到创建的bridge桥接网络
    9bea05bfbf3e   none        null      local
  2. 运行一个ubuntu镜像 , 此时就可以看到一个自定义的网络分配给镜像一个IP地址

    [root@centos7 ~]# docker run -it -d --network linux-net ubuntu  bash  # 使用自己创建的网络IP地址段 
    d3e0055679f71723b0a1b70339c763ba1b077903b77a0c5392bd9f6f2edaa350
    
    root@d3e0055679f7:/# apt install iproute2
    root@d3e0055679f7:/# ip a   # 拿到的IP地址是172.27.0.2/21
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
    815: eth0@if816: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
        link/ether 02:42:ac:1b:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
        inet 172.27.0.2/21 brd 172.27.7.255 scope global eth0   # 此时可以看到容器中就分配了一个自定义linux-net的IP地址
           valid_lft forever preferred_lft forever  
  3. 此时就可以ping通外网的地址

    root@d3e0055679f7:/# ping  baidu.com
    PING baidu.com (39.156.66.10) 56(84) bytes of data.
    64 bytes from baidu.com (39.156.66.10): icmp_seq=1 ttl=127 time=34.5 ms
    64 bytes from baidu.com (39.156.66.10): icmp_seq=2 ttl=127 time=33.2 ms
    64 bytes from baidu.com (39.156.66.10): icmp_seq=3 ttl=127 time=31.9 ms
    
    root@d3e0055679f7:/# ip r
    default via 172.27.0.1 dev eth0 
    172.27.0.0/21 dev eth0 proto kernel scope link src 172.27.0.2 
  4. 此时再启动一个容器A , 查看最新的容器IP地址 , 由于和上面创建的容器 , 在一个地址段 , 因此也可以进行通信

    [root@centos7 src]# docker run -it -p 80:80 --network linux-net nginx:v1 bash
    [root@b3afcaea2c02 /]# ip a  #查看新建的容器的IP地址是172.27.0.3 , 在同一个网段。
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
    61: eth0@if62: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
        link/ether 02:42:ac:1b:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
        inet 172.27.0.3/21 brd 172.27.7.255 scope global eth0
           valid_lft forever preferred_lft forever
  5. 为了将两个同主机且不在同一网段的容器进行通信

    [root@centos7 src]# iptables-save > iptables-rule.txt  #将iptables规则导出 , 然后修改此配置文件 , 注释掉以下两行
    #-A DOCKER-ISOLATION-STAGE-2 -o br-4e9a106f0e22 -j DROP
    #-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
     
    [root@centos-7 src]# iptables-restore  < iptables-rule.txt  # 再将iptables规则再导回来
  6. 然后开启桥接模式的容器B

    [root@centos7 ~]# docker run -it -d --network bridge ubuntu  #启动一个桥接模式的容器
    d481f620d2ada96e22df8931e765da2152ea06906d89cbb3f17b3f2fc46fd50b  
    
    [root@centos7 ~]# docker exec -it d4 bash
    root@d481f620d2ad:/# apt install iptuils-ping iproute2
    
    root@d481f620d2ad:/# ip a         # 获取的IP地址是10.10.0.3/16
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
    818: eth0@if819: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
        link/ether 02:42:0a:0a:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
        inet 10.10.0.2/16 brd 10.10.255.255 scope global eth0
           valid_lft forever preferred_lft forever
  7. 然后进入容器B中进行ping容器A的IP地址 , 此时就会基于iptables规则进行跨网段ping通

    root@d481f620d2ad:/# ip a      
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
    818: eth0@if819: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
        link/ether 02:42:0a:0a:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
        inet 10.10.0.2/16 brd 10.10.255.255 scope global eth0
           valid_lft forever preferred_lft forever
    root@d481f620d2ad:/# ping 172.27.0.2   #ping容器A的IP地址,此时可以ping通
    PING 172.27.0.2 (172.27.0.2) 56(84) bytes of data.
    64 bytes from 172.27.0.2: icmp_seq=1 ttl=63 time=0.210 ms
    64 bytes from 172.27.0.2: icmp_seq=2 ttl=63 time=0.057 ms
    64 bytes from 172.27.0.2: icmp_seq=3 ttl=63 time=0.051 ms


参考链接

Docker之八----容器之间互联与网络模式详解 - 一叶知秋~~ - 博客园 (cnblogs.com)

全网最详细的Docker网络教程详解 - 掘金 (juejin.cn)