Docker网络详解

07-14 1023阅读

Docker网络详解

Docker0网络

准备工作:清空所有的容器,清空所有的镜像

docker rm -f $(docker ps -a -q)             # 删除所有容器
docker rmi -f $(docker images -qa)          # 删除全部镜像

本地干净的网络

[root@kuangshenlinux ~]# ip addr
# 本地回环网络
1: lo:  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
       
# 网卡地址 wifi
2: enp0s3:  mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:e0:aa:73 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.111/24 brd 192.168.0.255 scope global noprefixroute enp0s3
       valid_lft forever preferred_lft forever
    inet6 fe80::3202:526:12cb:70ec/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
       
# docker 0 ,docker创建的网络
3: docker0:  mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:f8:9d:a8:42 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

1、微服务这么多,访问怎么解决? (容器名)

2、docker每启动一个容器,就会给他分配一个ip。docker0是docker默认给的。我们不指定网络的情况下,创建容器都在docker0中,未来开发,我们要自定义网络。

[root@kuangshenlinux ~]# docker run -itd --name web01 centos
Unable to find image 'centos:latest' locally
latest: Pulling from library/centos
a1d0c7532777: Already exists 
Digest: sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177
Status: Downloaded newer image for centos:latest
53231c3adf0423ed2d0577ead987507c12978416349a51445d663c9536c9b4ff
# docker每启动一个容器,就会给他分配一个ip。这个ip就是归docker0 管理
[root@kuangshenlinux ~]# docker exec -it web01 ip addr
1: lo:  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
4: eth0@if5:  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
# 容器外本地可以ping到容器里面
[root@kuangshenlinux ~]# ping 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.058 ms

分析原理

1、本来有三个网络,启动容器后,多了一个,这个网络和容器内部的网络是配对的。

# 再次启动一个容器查看
[root@kuangshenlinux ~]# docker exec -it web02 ip addr
1: lo:  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
6: eth0@if7:  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@kuangshenlinux ~]# ip addr
....
3: docker0:  mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:f8:9d:a8:42 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:f8ff:fe9d:a842/64 scope link 
       valid_lft forever preferred_lft forever
5: veth3b4847e@if4:  mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 0e:58:71:93:42:18 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::c58:71ff:fe93:4218/64 scope link 
       valid_lft forever preferred_lft forever
7: veth13568df@if6:  mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 9a:3c:71:70:e2:a0 brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet6 fe80::983c:71ff:fe70:e2a0/64 scope link 
       valid_lft forever preferred_lft forever
# 总结观察:
1、web1 -- linux 主机     5: veth3b4847e@if4:    4: eth0@if5
2、web2 -- linux 主机     7: veth13568df@if6:    6: eth0@if7
# 只要启动一个容器,默认就会分配一对网卡。
# 虚拟接口 # veth-pair 就是一对的虚拟设备接口,它都是成对出现的。一端连着协议栈,一端彼此相连着。
# 就好比一个桥梁,可以连通容器内外。
# 测试容器之间的访问,ip访问没有问题
[root@kuangshenlinux ~]# docker exec -it web02 ping 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.058 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.064 ms
^C
--- 172.17.0.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 0.058/0.061/0.064/0.003 ms
[root@kuangshenlinux ~]# docker exec -it web01 ping 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.043 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.071 ms
64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.092 ms
^C
--- 172.17.0.3 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2005ms
rtt min/avg/max/mdev = 0.043/0.068/0.092/0.022 ms

小结

Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。

Docker网络详解

Docker容器网络就很好的利用了Linux虚拟网络技术,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通(这样一对接口叫veth pair);

Docker中的网络接口默认都是虚拟的接口。虚拟接口的优势就是转发效率极高(因为Linux是在内核中进行数据的复制来实现虚拟接口之间的数据转发,无需通过外部的网络设备交换),对于本地系统和容器系统来说,虚拟接口跟一个正常的以太网卡相比并没有区别,只是他的速度快很多。

–link

mysql: 服务名地址链接 ip会变化

[root@kuangshenlinux ~]# docker exec -it web02 ping web01
ping: web01: Name or service not known
# 但是可以通过 --link在启动容器的时候连接到另一个容器网络中,可以通过域名ping了
[root@kuangshenlinux ~]# docker run -itd --name web03 --link web02  centos
6f67f9f7407edb8c48ce2d3ca413aef414a2a8628080fd69605e4ce2c3bea6ab
[root@kuangshenlinux ~]# docker exec -it web03 ping web02
PING web02 (172.17.0.3) 56(84) bytes of data.
64 bytes from web02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.062 ms
64 bytes from web02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.064 ms
64 bytes from web02 (172.17.0.3): icmp_seq=3 ttl=64 time=0.064 ms
^C
--- web02 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2005ms
rtt min/avg/max/mdev = 0.062/0.063/0.064/0.006 ms
# 但是反向也ping不通。
[root@kuangshenlinux ~]# docker exec -it web02 ping web03
ping: web03: Name or service not known
# 底层原理
域名: 
--link hosts 添加了一条记录
172.17.0.3   web02
[root@kuangshenlinux ~]# docker exec -it web03 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	web02 325795bd6df8
172.17.0.4	6f67f9f7407e
[root@kuangshenlinux ~]# 

–link是以前的方法,不方便了。

自定义网络

[root@kuangshenlinux ~]# docker network --help
Usage:  docker network COMMAND
Manage networks
Commands:
  connect     Connect a container to a network
  create      Create a network
  disconnect  Disconnect a container from a network
  inspect     Display detailed information on one or more networks
  ls          List networks
  prune       Remove all unused networks
  rm          Remove one or more networks
Run 'docker network COMMAND --help' for more information on a command.
# 查看所有的网络
[root@kuangshenlinux ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
defce6912c4a   bridge    bridge    local
e6e26ff63dfe   host      host      local
8a592709b443   none      null      local

所有网络模式

网络模式配置说明
bridge模式–net=bridge默认值,在Docker网桥docker0上为容器创建新的网络栈
none模式–net=none不配置网络,用户可以稍后进入容器,自行配置
container模式–net=container:name/id容器和另外一个容器共享Network namespace。 kubernetes中的pod就是多个容器共享一个Network namespace。
host模式–net=host容器和宿主机共享Network namespace
用户自定义–net=自定义网络用户自己使用network相关命令定义网络,创建容器的时候可以指定为自己定义的网络
[root@kuangshenlinux ~]# docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "defce6912c4ae8b16d6f02a6eee0650c79c7d39cba26597de32648f936c0cd43",
        "Created": "2023-12-12T19:57:25.572880728+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                	// 网络配置: config配置,子网网段 255*255. 65534 个地址
                    "Subnet": "172.17.0.0/16",
                    // docker0 网关地址
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        // 在这个网络下的容器地址。Name就是容器的名字
        "Containers": {
            "325795bd6df82e6ef18ff027f43a189c4ef886a25b95fdc9c5793bc9d7827179": {
                "Name": "web02",
                "EndpointID": "9ab43d4cd786b8c79d78fd3bf3f05c6dfbd6f1665ca5bc9e74646f1d6f758508",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            },
            "53231c3adf0423ed2d0577ead987507c12978416349a51445d663c9536c9b4ff": {
                "Name": "web01",
                "EndpointID": "b891d5b8213b8241b5438c60afc08054c0c4c48490a3715f21fe5591b28b65fc",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            },
            "6f67f9f7407edb8c48ce2d3ca413aef414a2a8628080fd69605e4ce2c3bea6ab": {
                "Name": "web03",
                "EndpointID": "651e2d1b9dcd72fc7339c687904cf763aaa524bd79cc5945888dfec8829a62b6",
                "MacAddress": "02:42:ac:11:00:04",
                "IPv4Address": "172.17.0.4/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@kuangshenlinux ~]# docker run -itd --name web01 --net bridge centos
552223f74f163f94238bf536040aa0c683b1ab0fbfbcabdd1ed28644e40f1b9f
# docker0网络的特点
	1.它是默认的
	2.域名访问不通
	3.--link 域名通了,但是删了又不行

create命令创建一个新的网络

[root@kuangshenlinux ~]# docker network create \
--driver bridge \
--subnet 192.169.0.0/16 \
--gateway 192.169.0.1 \ 
mynet
d37ec2853507c3e6159db06e4c8a33e39a45edff4ac69949c96f981d7aca9a79
[root@kuangshenlinux ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
defce6912c4a   bridge    bridge    local
e6e26ff63dfe   host      host      local
d37ec2853507   mynet     bridge    local
8a592709b443   none      null      local

使用的逻辑

# 未来可以通过网络来隔离项目
docker network create \
--driver bridge \
--subnet 192.169.0.0/16 \
--gateway 192.169.0.1 \ 
kuangstudynet
mysql
redis
web
admin
mq
# 部署集群挽环境,也可以这样定义网络
mysql  3-5个容器
docker network create \
--driver bridge \
--subnet 192.169.0.0/16 \
--gateway 192.169.0.1 \ 
mysqlnet
--net mysqlnet
# 启动两个服务在自己的网络下。  --net mynet
[root@kuangshenlinux ~]# docker run -itd --name wen01-net --net mynet centos
e16726178e4ee3b61b0dc47f16d112ba0426bcf040b84949811ebc8607d94555
[root@kuangshenlinux ~]# docker run -itd --name wen02-net --net mynet centos
17fae7a2c0bb66c2834ad7d3dc338c0a5707aea5caf4337138f15c6f2079713e
# 测试互相ping,可以使用域名ping通了
[root@kuangshenlinux ~]# docker exec -it wen01-net ping 192.169.0.3
PING 192.169.0.3 (192.169.0.3) 56(84) bytes of data.
64 bytes from 192.169.0.3: icmp_seq=1 ttl=64 time=0.063 ms
64 bytes from 192.169.0.3: icmp_seq=2 ttl=64 time=0.091 ms
64 bytes from 192.169.0.3: icmp_seq=3 ttl=64 time=0.066 ms
^C
--- 192.169.0.3 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2001ms
rtt min/avg/max/mdev = 0.063/0.073/0.091/0.014 ms
[root@kuangshenlinux ~]# docker exec -it wen01-net ping wen02-net
PING wen02-net (192.169.0.3) 56(84) bytes of data.
64 bytes from wen02-net.mynet (192.169.0.3): icmp_seq=1 ttl=64 time=0.041 ms
64 bytes from wen02-net.mynet (192.169.0.3): icmp_seq=2 ttl=64 time=0.064 ms
64 bytes from wen02-net.mynet (192.169.0.3): icmp_seq=3 ttl=64 time=0.106 ms
64 bytes from wen02-net.mynet (192.169.0.3): icmp_seq=4 ttl=64 time=0.088 ms
^C
--- wen02-net ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3007ms
rtt min/avg/max/mdev = 0.041/0.074/0.106/0.026 ms
[root@kuangshenlinux ~]# docker exec -it wen02-net ping wen01-net
PING wen01-net (192.169.0.2) 56(84) bytes of data.
64 bytes from wen01-net.mynet (192.169.0.2): icmp_seq=1 ttl=64 time=0.052 ms
64 bytes from wen01-net.mynet (192.169.0.2): icmp_seq=2 ttl=64 time=0.092 ms
^C
--- wen01-net ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 0.052/0.072/0.092/0.020 ms
# 未来在项目中,直接使用容器名来连接服务,ip无论怎么变,都不会发生变化
docker run -itd --name mysql --net mynet mysql
mysql:3306/rbms

网络连通

由于我们现在是跨网络的,容器之间无法访问

[root@kuangshenlinux ~]# docker exec -it web01 ping wen01-net
ping: wen01-net: Name or service not known
[root@kuangshenlinux ~]# docker exec -it web01 ping 192.169.0.2

docker0和自定义网络肯定不通,我们使用自定义网络的好处就是网络隔离:

大家公司项目部署的业务都非常多,假设我们有一个商城,我们会有订单业务(操作不同数据),会有订单业务购物车业务(操作不同缓存)。如果在一个网络下,有的程序猿的恶意代码就不能防止了,所以我们就在部署的时候网络隔离,创建两个桥接网卡,比如订单业务(里面的数据库,redis,mq,全部业务 都在order-net网络下)其他业务在其他网络。

那关键的问题来了,如何让 web-net-01 访问 web01?

[root@kuangshenlinux ~]# docker network connect --help
Usage:  docker network connect [OPTIONS] NETWORK CONTAINER
Connect a container to a network
# 第一个参数 网络
# 第二个参数 容器
[root@kuangshenlinux ~]# docker network connect mynet web01
[root@kuangshenlinux ~]# docker network inspect mynet
[
    {
        "Name": "mynet",
        "Id": "d37ec2853507c3e6159db06e4c8a33e39a45edff4ac69949c96f981d7aca9a79",
        "Created": "2023-12-12T20:34:57.1073687+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.169.0.0/16",
                    "Gateway": "192.169.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "17fae7a2c0bb66c2834ad7d3dc338c0a5707aea5caf4337138f15c6f2079713e": {
                "Name": "wen02-net",
                "EndpointID": "cd4963c8bc9e64182fffc5f7b202495c3c2b28d46da8e17d73d3a94359fd7c1d",
                "MacAddress": "02:42:c0:a9:00:03",
                "IPv4Address": "192.169.0.3/16",
                "IPv6Address": ""
            },
            # web01 这个容器进入了 mynet 网络
            "552223f74f163f94238bf536040aa0c683b1ab0fbfbcabdd1ed28644e40f1b9f": {
                "Name": "web01",
                "EndpointID": "d684b0ab3142219939957cbbd47a4a254d2459cbcac6fe9f9ae5aed0b7f32370",
                "MacAddress": "02:42:c0:a9:00:04",
                "IPv4Address": "192.169.0.4/16",
                "IPv6Address": ""
            },
            "e16726178e4ee3b61b0dc47f16d112ba0426bcf040b84949811ebc8607d94555": {
                "Name": "wen01-net",
                "EndpointID": "574b3b469f3c2f2f5c21725b720adeaa8640a47618f1d7d7ad8f279343f54c2b",
                "MacAddress": "02:42:c0:a9:00:02",
                "IPv4Address": "192.169.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]
[root@kuangshenlinux ~]# docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "defce6912c4ae8b16d6f02a6eee0650c79c7d39cba26597de32648f936c0cd43",
        "Created": "2023-12-12T19:57:25.572880728+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": {
            "26b67bff513034805ec998da0d36ff3b22eb27d2d5f93709f81adc7cc642d935": {
                "Name": "web02",
                "EndpointID": "db5229124ae6aee60f2fadd30c59fa0ec38dbde2a6ea325e50a943af9c97618c",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            },
            // web01 依旧存在
            "552223f74f163f94238bf536040aa0c683b1ab0fbfbcabdd1ed28644e40f1b9f": {
                "Name": "web01",
                "EndpointID": "d114e6a65bb580713542121454c5e5c9bb3d1151959cf40ec1e2c80e416240bb",
                "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": {}
    }
]

连接之后,web01这个容器拥有了两个ip。一个容器是可以有多个ip的。

#通过连接之后,网络就完全可以打通了
[root@kuangshenlinux ~]# docker exec -it web01 ping wen02-net
PING wen02-net (192.169.0.3) 56(84) bytes of data.
64 bytes from wen02-net.mynet (192.169.0.3): icmp_seq=1 ttl=64 time=0.047 ms
64 bytes from wen02-net.mynet (192.169.0.3): icmp_seq=2 ttl=64 time=0.064 ms
64 bytes from wen02-net.mynet (192.169.0.3): icmp_seq=3 ttl=64 time=0.140 ms
64 bytes from wen02-net.mynet (192.169.0.3): icmp_seq=4 ttl=64 time=0.069 ms
^C
--- wen02-net ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3014ms
rtt min/avg/max/mdev = 0.047/0.080/0.140/0.035 ms
[root@kuangshenlinux ~]# docker exec -it web02-net ping wen01
Error response from daemon: No such container: web02-net
[root@kuangshenlinux ~]# docker exec -it wen02-net ping web01
PING web01 (192.169.0.4) 56(84) bytes of data.
64 bytes from web01.mynet (192.169.0.4): icmp_seq=1 ttl=64 time=0.031 ms
64 bytes from web01.mynet (192.169.0.4): icmp_seq=2 ttl=64 time=0.063 ms
64 bytes from web01.mynet (192.169.0.4): icmp_seq=3 ttl=64 time=0.092 ms
^C
--- web01 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2001ms
rtt min/avg/max/mdev = 0.031/0.062/0.092/0.024 ms

结论:如果要跨网络操作别人,就需要使用 docker network connect [OPTIONS] NETWORK CONTAINER 连接。

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]