网络管理

Docker 网络模式

Docker 提供了几种不同的网络模式,用于容器与容器、主机以及外部网络之间的通信。主要的 Docker 网络模式包括:

Bridge(默认)

  • 默认网络模式。Docker 在主机上创建一个虚拟的网桥(例如 docker0),并将容器连接到该桥。容器之间可以通过桥接网络相互通信,也可以通过主机的 NAT 与外部网络通信。
  • 使用场景:适用于容器需要互相通信且不直接暴露给外部网络的情况。
docker run --network bridge ...

Host

  • 容器将使用主机的网络堆栈,不创建虚拟网桥。容器的网络直接与主机的网络共享,容器会使用主机的 IP 地址。
  • 使用场景:对网络性能要求较高或容器需要使用主机网络接口的场景。
docker run --network host ...

None

  • 禁用所有网络功能。容器将无法与外界通信,也无法与其他容器通信。
  • 使用场景:容器不需要网络的情况,或需要手动配置网络的情况。
docker run --network none ...

Container

  • 让一个容器共享另一个容器的网络堆栈。这样两个容器就像是在同一台主机上运行的进程一样共享 IP 地址和端口。
  • 使用场景:多个容器需要共享相同的网络环境。
docker run --network container:<other_container> ...

Overlay

  • 用于 Docker Swarm 或 Kubernetes 集群中,让不同主机上的容器可以通过虚拟网络进行通信。Overlay 网络可以跨主机创建虚拟网络,允许不同主机上的容器进行安全通信。
  • 使用场景:集群环境中跨主机的容器通信。
docker network create -d overlay my-overlay-network

Macvlan

  • 允许给每个容器分配一个独立的 MAC 地址,并将其作为主机网络的一部分。这使容器可以像物理主机一样直接连接到局域网中。
  • 使用场景:容器需要直接暴露在物理网络中,或需要与网络设备进行直接通信时。
docker network create -d macvlan --subnet=192.168.1.0/24 --gateway=192.168.1.1 -o parent=eth0 my-macvlan-network

前言

  • docker容器创建后,必不可少的要和其他主机或容器进行网络通信

  • 官方文档:https://docs.docker.com/network/

Docker默认的网络通信

默认docker安装后的网络设置

  • docker服务安装完成后,默认在每个宿主机会生成一个名为docker0的桥接网卡,此网卡IP默认为172.17.0.1/16

范例:

[root@docker ~]# ip a
...
docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:6c:0c:56:08 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
...

[root@docker ~]# brctl show
bridge name	bridge id		STP enabled	interfaces
docker0		8000.02426c0c5608	no		

默认创建容器后的网络配置

  • 每次创建容器后,宿主机就多了一个虚拟网卡 和容器内的网卡组合成一个网卡,通过docker0网桥实现互联互通
  • 容器会自动获取一个172.17.0.0/16网段内的IP地址,默认第一个为172.17.0.2 以此类推 172.17.0.3 ……
  • 容器获取的地址并不固定,每次容器重启,可能会发生地址变化

范例

#开启一个容器
[root@docker ~]# docker run -d --name centos01 centos:latest tail -f /etc/hosts

#查看宿主机新生成的网卡,编号为:@if11
[root@docker ~]# ip a
...
veth33d9370@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether c6:ca:da:8b:f8:db brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::c4ca:daff:fe8b:f8db/64 scope link 
       valid_lft forever preferred_lft forever

#查看容器内的网卡情况,编号为:@if12 ,IP:172.17.0.2
[root@docker ~]# docker exec -it centos01 bash
[root@30e4550d71f6 /]# ip a
...
eth0@if12: <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
       
#网桥情况
[root@docker ~]# brctl show
bridge name	bridge id		STP enabled	interfaces
docker0		8000.02426c0c5608	no		veth33d9370

#再开启一个容器
[root@docker ~]# docker run -d --name centos02 centos:latest tail -f /etc/hosts

#查看宿主机新生成的网卡,编号为:@if13
[root@docker ~]# ip a
12: veth33d9370@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether c6:ca:da:8b:f8:db brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::c4ca:daff:fe8b:f8db/64 scope link 
       valid_lft forever preferred_lft forever
14: veth645416a@if13: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 2a:11:c2:0e:7a:f8 brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet6 fe80::2811:c2ff:fe0e:7af8/64 scope link 
       valid_lft forever preferred_lft forever

#查看容器内新生成的网卡,编号为:@if14
[root@docker ~]# docker exec -it centos02 bash
[root@44bcfaa2d149 /]# ip a
...
13: eth0@if14: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

#查看最新的网桥情况
[root@docker ~]# brctl show
bridge name	bridge id		STP enabled	interfaces
docker0		8000.02426c0c5608	no		veth33d9370
						             	veth645416a

默认容器间的网络通信

  • **默认相同宿主机内 各容器间可以进行网络通信 **
  • 默认不同宿主机内 如果容器间IP冲突 将不能进行网络通信

范例:相同宿主机容器通信

  • 结论是 相同宿主机内 各容器间可以进行网络通信
[root@docker ~]# docker exec -it centos01 bash
[root@30e4550d71f6 /]# hostname -I
172.17.0.2

[root@docker ~]# docker exec -it centos02 bash
[root@44bcfaa2d149 /]# hostname -I
172.17.0.3

[root@44bcfaa2d149 /]# ping -c1 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.125 ms

[root@30e4550d71f6 /]# ping -c1 172.17.0.3
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.094 ms

禁止相同宿主机容器通信

#此选项实现禁止相同宿主机容器通信
[root@docker ~]# dockerd --help|grep icc
      --icc                                     Enable inter-container communication (default true)

#禁止
[root@docker ~]# vim /lib/systemd/system/docker.service 
...
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --icc=false
...
[root@docker ~]# systemctl daemon-reload 
[root@docker ~]# systemctl restart docker.service 

#测试
[root@30e4550d71f6 /]# ping -c1 172.17.0.3
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.

--- 172.17.0.3 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms
[root@44bcfaa2d149 /]# ping -c1 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.

--- 172.17.0.2 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

修改docker默认网桥

  • 新建容器默认使用docker0的网络配置,可以修改默认指向自定义的网桥网络

自定义网桥

  • 代替默认的docker0
#安装网桥工具包
[root@docker ~]# yum install -y bridge-utils

#添加一个br0网桥
[root@docker ~]# brctl addbr br0

#docker启动配置文件中添加 -b br0 即指定这个网桥为默认网桥
[root@docker ~]# vim /lib/systemd/system/docker.service 
...
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --icc=false -b br0
...
[root@docker ~]# systemctl daemon-reload 
[root@docker ~]# systemctl restart docker.service

#启动容器
[root@docker ~]# docker start centos01

#查看网桥情况,可以看到使用的是br0这个网桥
[root@docker ~]# brctl show
bridge name	  bridge id		      STP enabled	  interfaces
br0		      8000.b61ab8fbeec7	  no		      vethf3fe42d
docker0		  8000.0242a878326e	  no	

#查看网卡信息
[root@docker ~]# ip a
...
4: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether b6:1a:b8:fb:ee:c7 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.1/16 brd 172.18.255.255 scope global br0
       valid_lft forever preferred_lft forever
    inet6 fe80::403b:a4ff:fea3:9a29/64 scope link 
       valid_lft forever preferred_lft forever
...
7: vethf3fe42d@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br0 state UP group default 
    link/ether b6:1a:b8:fb:ee:c7 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::b41a:b8ff:fefb:eec7/64 scope link 
       valid_lft forever preferred_lft forever
...

-

容器名称互联

前言

  • 新建容器时,docker会自动分配 容器名称、容器ID 和 IP地址,这样会导致这些信息都不是固定的
  • 那么如何区分不同的容器,实现和确定目标容器的通信呢?解决方案是给容器起个固定的名称,容器间用这个固定的名称实现确定目标的互相通信
  • 有两种固定名称:
    • 容器名称
    • 容器名称的别名
    • 注意:两种方式都至少需要两个容器才能实现

通过自定义容器名称互联

容器名称介绍

  • 即在同一个宿主机上的容器之间通过自定义的名称实现互相访问
  • 比如:
  • 一个业务前端静态页面使用的是nginx,动态页面使用的是tomcat,另外还需要负载均衡调度器 如haproxy 对请求调度至nginx和tomcat的容器,由于容器在启动的时候其内部IP地址是DHCP随机分配的,而给容器起个固定的名称,则是相对比较固定的,因此比较适合此场景
  • 注意:如果被引用的容器地址变化,则必须重启当前容器才能生效
  • –link 本质上就是将目标容器的IP 和 自定义的名称|别名 做地址解析 从而实现互相通信

容器名称实现

  • docker run 创建容器,可使用 –link 选项实现容器名称的引用
[root@docker ~]# docker run --help | grep link
   --link list           #Add link to another container

#格式:
docker run --name <容器名称>                #先创建指定名称的容器
docker run --name --link <目标通信的容器ID或容器名称> #在创建容器时引用上面容器的名称

实战案例1:使用容器名称进行容器间通信

创建第一个容器

  • 创建指定名称的容器
[root@docker ~]# docker run -d --name centos01 centos:latest tail -f /etc/hosts

#查看相关信息
[root@docker ~]# docker exec -it centos01 bash
[root@57acb10ab6ba /]# 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
8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0
       valid_lft forever preferred_lft forever
[root@57acb10ab6ba /]# 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.18.0.2	57acb10ab6ba

创建第二个容器

  • 创建时引用第一个容器的名称
[root@docker ~]# docker run -d --name centos02 --link centos01 centos:latest tail -f /etc/hosts

#查看相关信息
[root@docker ~]# docker exec -it centos02 bash
[root@40f5b40c535d /]# 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
10: eth0@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:12:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.18.0.3/16 brd 172.18.255.255 scope global eth0
       valid_lft forever preferred_lft forever
[root@40f5b40c535d /]# 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.18.0.2	centos01 57acb10ab6ba #自动生成了名字解析
172.18.0.3	40f5b40c535d

测试访问

[root@docker ~]# docker exec -it centos02 bash
[root@40f5b40c535d /]# ping -c1 centos01
PING centos01 (172.17.0.2) 56(84) bytes of data.
64 bytes from centos01 (172.17.0.2): icmp_seq=1 ttl=64 time=0.099 ms

--- centos01 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.099/0.099/0.099/0.000 ms

#因为centos01没有link到centos02 所以没有生成名字解析 因此无法通过名称通信(这里的例子是直接将centos02当作url去解析了,64.32.28.238是美国的IP)
[root@57acb10ab6ba /]# ping -c1 centos02
PING a.17986.net (64.32.28.238) 56(84) bytes of data.
64 bytes from jiuyu.gicscorple.com (64.32.28.238): icmp_seq=1 ttl=127 time=209 ms

--- a.17986.net ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 208.769/208.769/208.769/0.000 ms

实战案例2:wordpress和MySQL两个容器实现互联

准备镜像

[root@docker ~]# docker pull wordpress:cli-php8.1

[root@docker ~]# docker pull mysql:5.7.37

准备所需配置文件

[root@docker ~]# tree lnmp_docker/
lnmp_docker/
├── mysql
│   ├── env_mysql.list
│   └── mysql_test.cnf
└── wordpress
    └── env_wordpress.list
    
[root@docker ~]# cat lnmp_docker/mysql/env_mysql.list 
MYSQL_ROOT_PASSWORD=123456
MYSQL_DATABASE=wordpress
MYSQL_USER=wpuser
MYSQL_PASSWORD=wppass

[root@docker ~]# cat lnmp_docker/mysql/mysql_test.cnf 
[mysqld]
server-id=100
log-bin=mysql-bin

[root@docker ~]# cat lnmp_docker/wordpress/env_wordpress.list 
WORDPRESS_DB_HOST=mysql:3306
WORDPRESS_DB_NAME=wordpress
WORDPRESS_DB_USER=wpuser
WORDPRESS_DB_PASSWORD=wppass
WORDPRESS_TABLE_PREFIX=wp_

运行mysql镜像

[root@docker ~]# docker run -d -p 3306:3306 --name mysql --env-file /root/lnmp_docker/mysql/env_mysql.list -v /root/lnmp_docker/mysql/:/etc/mysql/conf.d -v /data/mysql:/var/lib/mysql mysql:5.7.37

运行wordpress镜像

[root@docker ~]# docker run -d -p 80:80 --name wordpress --link mysql --env-file /root/lnmp_docker/wordpress/env_wordpress.list wordpress:cli-php8.1

浏览器测试访问

新版wordpress官方文档提示从 wp-config-docker.php 指定变量

通过自定义容器别名互联

容器别名介绍

  • 自定义的容器名称可能后期会发生变化,那么一旦名称发生变化,容器内程序之间也必须要随之发生变化,定义容器别名可以解决此问题
  • 比如:
  • 程序通过固定的容器名称进行服务调用,但是容器名称发生变化之后再使用之前的名称肯定是无法成功调用的,而每次都进行更改的话又比较麻烦,因此可以使用自定义别名去解决,即容器名称可以随意更改,只要不更改别名即可
  • –link 本质上就是将目标容器的IP 和 自定义的名称|别名 做地址解析 从而实现互相通信

容器别名实现

docker run --name <容器名称>   #先创建指定名称的容器

docker run --name <容器名称> --link <目标容器名称>:<容器别名1> [容器别名2]  #给上面创建的容器起别名,来创建新容器,定义多个别名的话需要""引起来

实战案例:使用容器别名

#定义第一个容器
[root@docker ~]# docker run -d --name centos01 centos:latest tail -f /etc/hosts

#定义第二个容器,指向第一个容器名称和别名
[root@docker ~]# docker run -d --name alpine01 --link centos01:centos01-alias  alpine:latest tail -f /etc/hosts
[root@docker ~]# docker exec -it alpine01 sh
/ # 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.2	centos01-alias d891540dbcd6 centos01 #名称和别名都有
172.17.0.3	4bb4587b2717
/ # ping -c1 centos01-alias
PING centos01-alias (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=2.514 ms

--- centos01-alias ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 2.514/2.514/2.514 ms
/ # ping -c1 centos01
PING centos01 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.262 ms

--- centos01 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.262/0.262/0.262 ms

容器名称最佳实践

  • link指向容器名称的同时 还要添加容器别名 实现双重保险
  • 通信时使用别名指定目标容器,以防止目标容器修改名称而导致访问失败

-

Docekr网络连接模式

docker支持的五种网络模式

  • bridge(默认值)
  • host
  • none
  • container
  • network-name(自定义网络模式)

查看默认的网络模式

[root@docker ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
67f2949fc823   bridge    bridge    local
2e991d9c8ca4   host      host      local
94d3be6288e6   none      null      local

网络模式指定

  • 默认新建的容器使用bridge模式
[root@docker ~]# docker run --help|grep net
   --network network      Connect a container to a network
   
docker run --network <mode>

#<mode>可以是以下值
none
bridge
host
container:<容器名或容器ID>
<自定义的网络名称>

bridge 模式

bridge模式概述

  • 本模式是docker的默认模式,即不指定任何模式就是bridge模式,也是使用比较多的模式
  • 此模式创建的容器会为每一个容器分配自己的网络IP等信息,并将容器连接到一个虚拟网桥(默认docker0为虚拟网桥)从而实现与外部网络通信
  • 容器可以和外部网络直接进行通信,通过SNAT访问外网,使用DNAT使容器可以被外部主机访问,所以此模式又称NAT模式
  • 此模式宿主机需要开启 ip_forward 功能(安装docker时自动启用)

bridge模式特点

  • 网络资源隔离:不同宿主机的容器无法直接通信,各自使用独立的网络
  • 无需手动配置:容器默认自动获取172.17.0.0/16的IP地址,此地址可以修改
  • 可以访问外网:利用宿主机的物理网卡,SNAT连接外网
  • 外部主机无法直接访问容器:可以通过配置DNAT接受外网的访问
  • 网络性能较低:因为NAT会带来网络性能的损耗
  • 端口管理繁琐:每个容器必须手动指定唯一的端口,容易产生端口冲突

查看bridge模式信息

[root@docker ~]# docker network inspect bridge 
[
    {
        "Name": "bridge",
        "Id": "67f2949fc82390f1dc3c39ef42d4ae4ff921f7c7bf5b6ca4bf82a2d320e90e21",
        "Created": "2022-02-01T21:49:18.21589083+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "4bb4587b27173a21258795c4fffea6281ce81bf8134b293a1b0e1af08726fcff": {
                "Name": "alpine01",
                "EndpointID": "8ff10312c5e2be0053cf62568d14fec9b7010b1304565f24b14c2ead5f22e05d",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            },
            "d891540dbcd63154dfffcb4b563768b0f517d22e62224497c08c539eea1bea37": {
                "Name": "centos01",
                "EndpointID": "1a0b961919806d8dd8c6c4b4ac8c93d78b1a2663c9f08501b47d333b49f27c2d",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

查看宿主机信息

[root@docker ~]# cat /proc/sys/net/ipv4/ip_forward
1 #安装docker时自动启用了

[root@docker ~]# iptables -vnL
...

[root@docker ~]# iptables -t nat -vnL
...

修改bridge模式默认网段方法一

  • 此方法除了更改默认网段外,还可以进行详细的配置
  • 常用

查看默认的网段

#宿主机网桥网段:172.17.0.1/16
[root@docker ~]# ip a
...
docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:a8:78:32:6e 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:a8ff:fe78:326e/64 scope link 
       valid_lft forever preferred_lft forever
       
#容器,默认不指定网络模式即使用bridge模式
#容器默认分配的IP地址:172.17.0.2/16
[root@docker ~]# docker run --rm -it centos:latest bash
[root@0983ce3cba14 /]# ip a
...
eth0@if35: <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

修改默认网段

[root@docker ~]# vim /etc/docker/daemon.json 
{
  "registry-mirrors": ["https://jqm0rnhf.mirror.aliyuncs.com"],
  "dns": ["114.114.114.114","223.5.5.5"],
  "dns-search": ["azheng.vip","azheng.com"],
  "bip": "192.168.1.1/24", #docker0网卡的默认IP,24表示容器IP的子网掩码
  "fixed-cidr": "192.168.1.0/25", #限制Docker容器获取IP的范围,如docker0的IP为172.17.0.1/16,可将一fixed-cidr设为172.17.1.1/24,那么Docker容器的IP范围将为172.17.1.1~172.17.1.254
  "fixed-cidr-v6": "2001:db8::/64",
  "mtu": 1500, #指定dockero的最大传输单元,BYTES
  "default-gateway": "192.168.1.254", #网关必须和bip在同一个网段
  "default-gateway-v6": "2001:db8:abcd::89"
}

重启生效

[root@docker ~]# systemctl restart docker.service 

查看结果

#宿主机
[root@docker ~]# ip a
...
docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:a8:78:32:6e brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.1/24 brd 192.168.1.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:a8ff:fe78:326e/64 scope link 
       valid_lft forever preferred_lft forever
       
#容器
[root@docker ~]# docker run --rm -it centos:latest bash
[root@1caf08f375a9 /]# ip a
...
38: eth0@if39: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:c0:a8:01:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.1.2/24 brd 192.168.1.255 scope global eth0
       valid_lft forever preferred_lft forever
[root@1caf08f375a9 /]# cat /etc/resolv.conf 
search azheng.vip azheng.com
nameserver 114.114.114.114
nameserver 223.5.5.5

修改bridge模式默认网段方法二

  • 只是修改默认网段
  • 不常用

查看默认的网段

#宿主机网桥网段:172.17.0.1/16
[root@docker ~]# ip a
...
docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:a8:78:32:6e 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:a8ff:fe78:326e/64 scope link 
       valid_lft forever preferred_lft forever
       
#容器,默认不指定网络模式即使用bridge模式
#容器默认分配的IP地址:172.17.0.2/16
[root@docker ~]# docker run --rm -it centos:latest bash
[root@0983ce3cba14 /]# ip a
...
eth0@if35: <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

修改默认网段

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

查看修改后的网段

#宿主机,已经修改为 10.100.0.1/24 网段
[root@docker ~]# ip a
...
docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:a8:78:32:6e brd ff:ff:ff:ff:ff:ff
    inet 10.100.0.1/24 brd 10.100.0.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:a8ff:fe78:326e/64 scope link 
       valid_lft forever preferred_lft forever
       
#创建容器测试,分配了一个 10.100.0.2/24 的IP
[root@docker ~]# docker run --rm -it centos:latest bash
[root@97a92c2d9b72 /]# ip a
...
eth0@if37: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:0a:64:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.100.0.2/24 brd 10.100.0.255 scope global eth0
       valid_lft forever preferred_lft forever

查看修改后的bridge模式信息

[root@docker ~]# docker network inspect bridge 
[
    {
        "Name": "bridge",
        "Id": "54b8c43eb243a014ee3758bed4b8011b8e7d350a47d25827399243d9b3ce01ce",
        "Created": "2022-02-02T02:06:49.00279079+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "10.100.0.0/24",
                    "Gateway": "10.100.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

host 模式

host模式概述

  • 如果指定host模式启动容器,那么新创建的容器不会创建自己的虚拟网卡,而是直接使用宿主机的网卡和IP地址
  • 因此在容器里面查看到的IP信息就是宿主机的信息,访问容器的时候直接使用宿主机IP+容器端口即可,不过容器内除网络以外的其他资源,如:文件系统、系统进程等仍然和宿主机保持隔离

host模式特点

  • 使用参数 –network host 指定
  • 共享宿主机网络
  • 网络性能无损耗
  • 网络故障排除相对简单
  • 各容器网络无隔离
  • 网络资源无法分别统计
  • 端口管理困难(容易产生端口冲突)
  • 不支持端口映射

实现host模式

#实现前80端口未开启
[root@docker ~]# ss -ntl|grep 80

#用host模式启动nginx容器
[root@docker ~]# docker run -d --network host nginx:latest

#端口开启
[root@docker ~]# ss -ntl|grep 80
LISTEN    0         128                0.0.0.0:80               0.0.0.0:*       
LISTEN    0         128                   [::]:80                  [::]:*   

#访问测试
[root@docker ~]# curl 127.0.0.1
...
<title>Welcome to nginx!</title>
...

#其他主机访问测试
[root@18 ~]# curl 10.0.0.8
...
<title>Welcome to nginx!</title>
...

none模式

none模式概述

  • 在使用none模式后,docker容器不会进行任何网络配置,没有网卡、没有IP也没有路由,因此无法与外界进行网络通信,需要手动添加网卡配置IP等,所以极少使用

none模式特点

  • 使用参数 –network none 指定
  • 默认无网络功能,无法和外部通信

container 模式

container模式概述

  • 使用此模式创建的容器需指定一个已存在的容器 并和其共享一个网络、IP、和端口范围
  • 不能和指定容器的端口冲突
  • 除了网络之外的文件系统、进程等信息等仍然保持互相隔离
  • 两个容器的进程可以通过lo网卡进行通信

container模式特点

  • 使用参数 –network container:指定的容器名称或ID 来实现
  • 与宿主机网络空间隔离
  • 与容器间共享网络(直接使用指定容器的网络)
  • 适合容器间频繁通信的场景
  • 较少使用

自定义网络模式

自定义网络模式概述

  • 自定义网段地址,网关等信息
  • 注意:自定义网络内的容器可以直接通过容器名进行相互的访问,而无需使用 –link
  • 可以使用自定义网络模式,实现不同集群应用的独立网络管理,进而互相不受影响,而且在同一个网络内 可以直接使用容器名互相访问 非常便利
  • 生产中常用

自定义网络相关指令

[root@docker ~]# docker network create --help

Usage:  docker network create [OPTIONS] NETWORK

Create a network

Options:
...

创建自定义网络

docker network create [-d <mode>] --subnet <CIDR> --gateway <网关> <自定义网络名称>

#注意:mode不支持host和none
#不使用-d指定网络模式则默认使用bridge模式

查看自定义网络信息

docker network inspect <自定义网络名称或网络ID>

引用自定义网络

docker run --network <自定义网络名称> <镜像名称>

删除自定义网络

docker network rm <自定义网络名称或网络ID>

实战案例:创建自定义的网络

#创建自定义的网络
[root@docker ~]# docker network create -d bridge --subnet 172.27.0.0/16 --gateway 172.27.0.1 test-net

#查看生成的自定义网络
[root@docker ~]# docker network ls
NETWORK ID     NAME       DRIVER    SCOPE
...
97447d7d0c3f   test-net   bridge    local
[root@docker ~]# docker network inspect test-net 
[
    {
        "Name": "test-net",
        "Id": "97447d7d0c3fd16ecc7775fcb8316167950a37032d19744092ffd706c9d201cd",
        "Created": "2022-02-02T05:40:55.202778966+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.27.0.0/16",
                    "Gateway": "172.27.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

#宿主机生成了一个新的网桥和网卡
[root@docker ~]# brctl show
bridge name	        bridge id		   STP enabled	 interfaces
br-97447d7d0c3f		8000.024290b54a05	 no		
[root@docker ~]# ip a
...
br-97447d7d0c3f: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:90:b5:4a:05 brd ff:ff:ff:ff:ff:ff
    inet 172.27.0.1/16 brd 172.27.255.255 scope global br-97447d7d0c3f
    
#宿主机生成了新的路由表
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
172.27.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-97447d7d0c3f
...

利用自定义的网络创建容器

[root@docker ~]# docker run -it --rm  --network test-net centos:latest bash

[root@02a0e63e75a5 /]# ip a
...
45: eth0@if46: <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/16 brd 172.27.255.255 scope global eth0
       valid_lft forever preferred_lft forever

[root@02a0e63e75a5 /]# ping -c1 www.baidu.com
PING www.a.shifen.com (39.156.66.14) 56(84) bytes of data.
64 bytes from 39.156.66.14 (39.156.66.14): icmp_seq=1 ttl=127 time=28.6 ms

--- www.a.shifen.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms

[root@02a0e63e75a5 /]# cat /etc/resolv.conf 
search azheng.vip azheng.com
nameserver 127.0.0.11
options ndots:0

实战案例:多个容器间利用自定义网络实现通信

  • 结论:在同一个自定义网络中的容器可以通过容器名称直接进行访问
#查看自定义网络信息
[root@docker ~]# docker network ls
NETWORK ID     NAME       DRIVER    SCOPE
...
97447d7d0c3f   test-net   bridge    local

#创建两个容器,使用自定义网络,名称设为test1 和 test2
[root@docker ~]# docker run -d --network test-net --name test1 centos:latest tail -f /etc/hosts
7d2224c56a15d0a203b6571cb8e41524e231ca73a3f8977f35e12bd913d470b6
[root@docker ~]# docker run -d --network test-net --name test2 centos:latest tail -f /etc/hosts
80a727f61dbc8068da880cb4bb2568279a0359cd74ba450a456d2728ad42e9e1

#进入test1容器 利用名称测试访问test2容器测试
[root@docker ~]# docker exec -it test1 bash
[root@7d2224c56a15 /]# ping -c1 test1
PING test1 (172.27.0.2) 56(84) bytes of data.
64 bytes from 7d2224c56a15 (172.27.0.2): icmp_seq=1 ttl=64 time=0.031 ms

--- test1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.031/0.031/0.031/0.000 ms

#进入test2容器 利用名称测试访问test1容器测试
[root@docker ~]# docker exec -it test2 bash
[root@80a727f61dbc /]# ping -c1 test2
PING test2 (172.27.0.3) 56(84) bytes of data.
64 bytes from 80a727f61dbc (172.27.0.3): icmp_seq=1 ttl=64 time=0.067 ms

--- test2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.067/0.067/0.067/0.000 ms

#test1详细信息
[root@7d2224c56a15 /]# 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
47: eth0@if48: <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/16 brd 172.27.255.255 scope global eth0
       valid_lft forever preferred_lft forever
[root@7d2224c56a15 /]# 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.27.0.2	7d2224c56a15

#test2详细信息
[root@80a727f61dbc /]# 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
49: eth0@if50: <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/16 brd 172.27.255.255 scope global eth0
       valid_lft forever preferred_lft forever
[root@80a727f61dbc /]# 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.27.0.3	80a727f61dbc

实战案例:利用自定义网络实现 Redis Cluster

创建自定义网络

#不使用-d指定网络模式则默认使用bridge模式
[root@docker ~]# docker network create --subnet 172.30.0.0/16 net-redis

利用脚本准备redis容器配置文件

[root@docker ~]# vim create_rediscnf.sh
#!/bin/bash
for node in {1..6};do
    mkdir -p /data/redis/redis-node${node}/conf
    cat > /data/redis/redis-node${node}/conf/redis.conf <<EOF
port 6379
bind 0.0.0.0
requirepass 123456
masterauth 123456
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done

[root@docker ~]# bash create_rediscnf.sh

利用脚本启动所有容器

[root@docker ~]# vim run_rediscon.sh
#!/bin/bash
for node in {1..6};do
    docker run -d \
    --name redis-node${node} \
    -p 637${node}:6379 \
    -p 1637${node}:16379 \
    -v /data/redis/redis-node${node}/conf/redis.conf:/etc/conf/redis.conf \
    -v /data/redis/redis-node${node}/data:/data --network net-redis \
    redis:6.2.6 redis-server /etc/conf/redis.conf
done

[root@docker ~]# bash run_rediscon.sh

进入任意一个redis容器创建集群

[root@docker ~]# docker exec -it redis-node3 sh
# redis-cli -a 123456 --cluster create 172.30.0.2:6379 172.30.0.3:6379 172.30.0.4:6379 172.30.0.5:6379 172.30.0.6:6379 172.30.0.7:6379 --cluster-replicas 1
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 172.30.0.6:6379 to 172.30.0.2:6379
Adding replica 172.30.0.7:6379 to 172.30.0.3:6379
Adding replica 172.30.0.5:6379 to 172.30.0.4:6379
M: 3d10110ccd94ce4a8ff5e3954575d89a008c5bdf 172.30.0.2:6379
   slots:[0-5460] (5461 slots) master
M: 55e3b2ec99d69bc466973970c1efd2682ea96612 172.30.0.3:6379
   slots:[5461-10922] (5462 slots) master
M: eccde3447a4faf5da5def19a3dc9f64a8361bd5c 172.30.0.4:6379
   slots:[10923-16383] (5461 slots) master
S: 5f4888b82035837eab18632075794baf4f99e95d 172.30.0.5:6379
   replicates eccde3447a4faf5da5def19a3dc9f64a8361bd5c
S: 8c40be55e178279f3f46812a6f65728fe701bb4c 172.30.0.6:6379
   replicates 3d10110ccd94ce4a8ff5e3954575d89a008c5bdf
S: b67aea842a4aa3b47499997519b3b4cf6a89f94e 172.30.0.7:6379
   replicates 55e3b2ec99d69bc466973970c1efd2682ea96612
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
.
>>> Performing Cluster Check (using node 172.30.0.2:6379)
M: 3d10110ccd94ce4a8ff5e3954575d89a008c5bdf 172.30.0.2:6379
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: 8c40be55e178279f3f46812a6f65728fe701bb4c 172.30.0.6:6379
   slots: (0 slots) slave
   replicates 3d10110ccd94ce4a8ff5e3954575d89a008c5bdf
M: eccde3447a4faf5da5def19a3dc9f64a8361bd5c 172.30.0.4:6379
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
M: 55e3b2ec99d69bc466973970c1efd2682ea96612 172.30.0.3:6379
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: 5f4888b82035837eab18632075794baf4f99e95d 172.30.0.5:6379
   slots: (0 slots) slave
   replicates eccde3447a4faf5da5def19a3dc9f64a8361bd5c
S: b67aea842a4aa3b47499997519b3b4cf6a89f94e 172.30.0.7:6379
   slots: (0 slots) slave
   replicates 55e3b2ec99d69bc466973970c1efd2682ea96612
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

确认分配状态

# redis-cli -a 123456 cluster nodes
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
b67aea842a4aa3b47499997519b3b4cf6a89f94e 172.30.0.7:6379@16379 slave 55e3b2ec99d69bc466973970c1efd2682ea96612 0 1643774953279 2 connected
8c40be55e178279f3f46812a6f65728fe701bb4c 172.30.0.6:6379@16379 slave 3d10110ccd94ce4a8ff5e3954575d89a008c5bdf 0 1643774953583 1 connected
eccde3447a4faf5da5def19a3dc9f64a8361bd5c 172.30.0.4:6379@16379 myself,master - 0 1643774953000 3 connected 10923-16383
5f4888b82035837eab18632075794baf4f99e95d 172.30.0.5:6379@16379 slave eccde3447a4faf5da5def19a3dc9f64a8361bd5c 0 1643774954302 3 connected
3d10110ccd94ce4a8ff5e3954575d89a008c5bdf 172.30.0.2:6379@16379 master - 0 1643774952569 1 connected 0-5460
55e3b2ec99d69bc466973970c1efd2682ea96612 172.30.0.3:6379@16379 master - 0 1643774953000 2 connected 5461-10922
#下面是master/slave的对应关系
#172.30.0.2 <---> 172.30.0.6
#172.30.0.3 <---> 172.30.0.7
#172.30.0.4 <---> 172.30.0.5
# 
# redis-cli -a 123456 cluster info
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:3
cluster_stats_messages_ping_sent:747
cluster_stats_messages_pong_sent:723
cluster_stats_messages_meet_sent:1
cluster_stats_messages_sent:1471
cluster_stats_messages_ping_received:723
cluster_stats_messages_pong_received:748
cluster_stats_messages_received:1471

测试写入数据

# redis-cli -a 123456 -h 172.30.0.2 
172.30.0.2:6379> set xiang zheng
(error) MOVED 11569 172.30.0.4:6379 #在172.30.0.2写入数据,提示需要到172.30.0.4上写入数据

# redis-cli -a 123456 -h 172.30.0.4
172.30.0.4:6379> set xiang zheng #数据写入成功
OK
172.30.0.4:6379> get xiang #查看key
"zheng"
172.30.0.4:6379> set haha xixi
(error) MOVED 3662 172.30.0.2:6379 #再次写入数据,提示需要到172.30.0.2上写入数据

# redis-cli -a 123456 -h 172.30.0.2
172.30.0.2:6379> get haha
(nil)
172.30.0.2:6379> set haha xixi
OK
172.30.0.2:6379> get haha
"xixi"
172.30.0.2:6379> get xiang
(error) MOVED 11569 172.30.0.4:6379 #提示去172.30.0.4查看此key(结论:key在哪里设置的就要去哪里查看)

模仿故障测试redis cluster高可用性

#master/slave的对应关系
#172.30.0.2 <---> 172.30.0.6
#172.30.0.3 <---> 172.30.0.7
#172.30.0.4 <---> 172.30.0.5

#模拟172.30.0.3故障
[root@docker ~]# docker stop redis-node2

#进入一个正常运行的容器,查看主从切换状态
#可以看到172.30.0.3被标记为fail状态,而172.30.0.7取而代之成为master
[root@docker ~]# docker exec -it redis-node1 sh
# redis-cli -a 123456 cluster nodes
8c40be55e178279f3f46812a6f65728fe701bb4c 172.30.0.6:6379@16379 slave 3d10110ccd94ce4a8ff5e3954575d89a008c5bdf 0 1643776779566 1 connected
eccde3447a4faf5da5def19a3dc9f64a8361bd5c 172.30.0.4:6379@16379 master - 0 1643776779463 3 connected 10923-16383
55e3b2ec99d69bc466973970c1efd2682ea96612 172.30.0.3:6379@16379 master,fail - 1643776681323 1643776679000 2 connected
3d10110ccd94ce4a8ff5e3954575d89a008c5bdf 172.30.0.2:6379@16379 myself,master - 0 1643776778000 1 connected 0-5460
5f4888b82035837eab18632075794baf4f99e95d 172.30.0.5:6379@16379 slave eccde3447a4faf5da5def19a3dc9f64a8361bd5c 0 1643776778444 3 connected
b67aea842a4aa3b47499997519b3b4cf6a89f94e 172.30.0.7:6379@16379 master - 0 1643776778000 7 connected 5461-10922

恢复容器查看是否正常

#恢复前是172.30.0.3被标记为fail状态,而172.30.0.7取而代之成为master

#可以看到172.30.0.3已经恢复,但是已经成为172.30.0.7的从
# redis-cli -a 123456 cluster nodes
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
8c40be55e178279f3f46812a6f65728fe701bb4c 172.30.0.6:6379@16379 slave 3d10110ccd94ce4a8ff5e3954575d89a008c5bdf 0 1643776994784 1 connected
eccde3447a4faf5da5def19a3dc9f64a8361bd5c 172.30.0.4:6379@16379 master - 0 1643776994279 3 connected 10923-16383
55e3b2ec99d69bc466973970c1efd2682ea96612 172.30.0.3:6379@16379 slave b67aea842a4aa3b47499997519b3b4cf6a89f94e 0 1643776995087 7 connected
3d10110ccd94ce4a8ff5e3954575d89a008c5bdf 172.30.0.2:6379@16379 myself,master - 0 1643776994000 1 connected 0-5460
5f4888b82035837eab18632075794baf4f99e95d 172.30.0.5:6379@16379 slave eccde3447a4faf5da5def19a3dc9f64a8361bd5c 0 1643776995289 3 connected
b67aea842a4aa3b47499997519b3b4cf6a89f94e 172.30.0.7:6379@16379 master - 0 1643776994000 7 connected 5461-10922

Docekr 相关网卡名说明

br-47e5d37b275e、br-6c86cb414c23、vethf3757ed@if17、vethc33f412@if19,这些都是什么网卡名

这些都是 Docker 网络相关的组件。

  • br-47e5d37b275ebr-6c86cb414c23 是 Docker 容器网络的虚拟网桥,用于连接不同的容器。每个容器都会被分配一个虚拟网卡(veth 设备)和一个 IP 地址,该 IP 地址可以由 Docker 管理员指定或动态生成。
  • vethf3757ed@if17vethc33f412@if19 则是虚拟以太网设备,它们是容器网络中的一部分。每个容器都会分配一个 veth 设备对,其中一个 veth 设备连接到容器内部的网络命名空间中,另一个 veth 设备则连接到宿主机上的虚拟网桥上。在上述示例中,vethf3757ed@if17 设备连接到容器中,vethc33f412@if19 设备连接到 br-47e5d37b275e 虚拟网桥。

总之,这些网卡名是 Docker 容器网络的一部分,用于连接和管理不同的容器。

-

实现同一个宿主机中不同网络的容器间通信

测试环境

  • 假设 同一个宿主机中 开启两个容器 一个使用默认的docker0网络 一个使用自定义的网络 那么默认会因为iptables规则的问题而无法相互进行通信
[root@docker ~]# docker run -d --name centos01 centos:latest tail -f /etc/hosts

[root@docker ~]# docker run -d --network test-net --name centos02 centos:latest tail -f /etc/hosts

[root@docker ~]# docker inspect -f "{{.NetworkSettings.IPAddress}}" centos01
10.0.0.1

[root@docker ~]#  docker inspect  centos02 | grep -i ipaddress
"IPAddress": "172.27.0.2",

[root@docker ~]# docker exec -it centos01 bash
[root@287b8b5215f4 /]# ping -c1 172.27.0.2
PING 172.27.0.2 (172.27.0.2) 56(84) bytes of data.
From 192.168.1.2 icmp_seq=1 Destination Host Unreachable

--- 172.27.0.2 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms

方法一:通过iptanles实现

#首先确认已经开启路由转发功能
[root@docker ~]# cat /proc/sys/net/ipv4/ip_forward
1 #1表示已经开启路由转发

#默认网络和自定义网络使用的是不同的网桥
[root@docker ~]# brctl show
bridge name      	bridge id		  STP enabled	interfaces
...
br-97447d7d0c3f		8000.024290b54a05	 no		    vetha0ef6a4
docker0		        8000.0242a878326e	 no	     	vethf931d31

#宿主机 iptables 规则
[root@docker ~]# iptables-save 
...
*filter
...
-A DOCKER-ISOLATION-STAGE-2 -o br-97447d7d0c3f -j DROP #注意观察此行
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP #注意观察此行
...

#修改iptables规则方式一
[root@docker ~]# mkdir -p /iptables
[root@docker ~]# iptables-save > /iptables/iptables.rule
[root@docker ~]# vim /iptables/iptables.rule
...
-A DOCKER-ISOLATION-STAGE-2 -o br-97447d7d0c3f -j ACCEPT #修改此行
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j ACCEPT #修改此行
...
[root@docker ~]# iptables-restore < /iptables/iptables.rule


#修改iptables规则方式二
-A DOCKER-ISOLATION-STAGE-2  -j ACCEPT #执行

方法二:通过 docker network connect 命令实现

  • 将容器连接到一个网络(本质上就是在指定的容器添加一块和目标网络相同的网卡)

    • #Connect a container to a network
      Usage:  docker network connect [OPTIONS] NETWORK CONTAINER
  • 断开容器与网络的连接

    • #Disconnect a container from a network
      Usage:  docker network disconnect [OPTIONS] NETWORK CONTAINER

打通连接

#让centos01可以连接到test-net的网络
[root@docker ~]# docker network connect test-net centos01 
#测试访问
[root@docker ~]# docker exec -it centos01 bash
[root@287b8b5215f4 /]# ping  -c1 172.27.0.3   
PING 172.27.0.3 (172.27.0.3) 56(84) bytes of data.
64 bytes from 172.27.0.3: icmp_seq=1 ttl=64 time=0.067 ms


#让centos02可以连接到bridge的网络
[root@docker ~]# docker network connect bridge centos02
#测试访问
[root@726408f63f50 /]# ping 10.0.0.1
PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_seq=12 ttl=64 time=0.231 ms

断开连接

#让centos01不可以连接到test-net的网络
[root@docker ~]# docker network disconnect test-net centos01 

#让centos01不可以连接到bridge的网络
[root@docker ~]# docker network disconnect bridge centos01 

-

实现跨宿主机的容器之间网络通信

-

实战案例:利用docker结合负载均衡实现网络架构高可用