Py学习  »  docker

Docker学习(七)网络

我犟不过你 • 3 年前 • 297 次点击  

一、网络

1、宿主机本地网络

通过ip addr(我使用的ECS centos7.6)查看当前宿主机本地网络。

[root@iZ2ze7sn66bchxncut8rgsZ /]# ip addr
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 fq_codel state UP group default qlen 1000
    link/ether 00:16:3e:2c:ca:40 brd ff:ff:ff:ff:ff:ff
    inet 172.28.47.71/20 brd 172.28.47.255 scope global dynamic noprefixroute eth0
       valid_lft 314163481sec preferred_lft 314163481sec
    inet6 fe80::216:3eff:fe2c:ca40/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:a5:96:b1:de 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:a5ff:fe96:b1de/64 scope link 
       valid_lft forever preferred_lft forever

发现上述结果中存在一个docker0的网卡,ip网段为172.17.0.1/16,docker容器会自动桥街到该网络上。

2、docker网络模式

[root@iZ2ze7sn66bchxncut8rgsZ /]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
bcea3a512ca5        bridge              bridge              local
c6ec1c6228b7        host                host                local
25081d2267a8        none                null                local

使用docker network ls 可以查看当前docker的三种默认网络模式,分别是bridge桥连,host主机,以及none。其实docker还有一种网络模式:container模式。下面我们具体分下下四种模式。

bridge模式:

bridge模式是Docker默认的网络设置,此模式会为每一个容器分配Network Namespace、设置IP等,并将并将一个主机上的Docker容器连接到一个虚拟网桥上。在1中看到的宿主机网络中的docker0就是单独给docker服务分配的虚拟网桥。

我们启动之前课程构建的nginx,或者其他容器也可以

 docker run -d --name nginx-bridge -p 8080:80 nginx:v1

进入容器内,查看ip,发现ip是172.17.0.2

[root@iZ2ze7sn66bchxncut8rgsZ opt]# docker exec -it nginx-bridge bash
[root@8245c09083ae /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:ac:11:00:02  txqueuelen 0  (Ethernet)
        RX packets 53  bytes 5068 (4.9 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 22  bytes 3282 (3.2 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

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

查看下宿主机的ip设备,发现多了一个虚拟网卡,该网卡是与容器成对的,这里Docker Daemon 利用 veth pair 了技术:

宿主机ip addr

由上面的步骤我们能够推断出docker 容器的bridge网络模型搭嘎如下图:

bridge网络模型
host模式:

如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。

启动一个使用host模式的容器,需要指定--net host参数,发现提示使用host网络模式时,映射端口是无效的,其实不难理解,因为容器公用宿主机的网卡eth0。

[root@iZ2ze7sn66bchxncut8rgsZ opt]# docker run -d --name nginx-bridge -p 8000:80 --net host  nginx:v1
WARNING: Published ports are discarded when using host network mode
39840be17832820b37dd23d2c406c8fd2c11111cc3989ff155036f2a1ea8e632

查看当前宿主机ip,看看我们上一步推测是否正确:

宿主机

查看容器的ip:

容器

上面两幅图发现,容器与宿主机的ip完全相同,在容器中可以操作宿主机的全部网络设备,网络隔离性很差,安全性也很差,我们可以得到以下host网络模式的模型。

host
none模式:

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

docker run -d --name nginx-bridge -p 8000:80 --net none  nginx:v1

进入容器查看其ip:

容器
container模式:

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

先启动一个默认桥连的容器:

[root@iZ2ze7sn66bchxncut8rgsZ opt]# docker run -it --name nginx-bridge -p 8080:80 nginx:v1 bash
[root@f317a0dc60ee /]# ifconfig 
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:ac:11:00:02  txqueuelen 0  (Ethernet)
        RX packets 26  bytes 2261 (2.2 KiB)
        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

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

再启动一个使用container模式的容器。

[root@iZ2ze7sn66bchxncut8rgsZ opt]# docker run -it --name nginx-c --net container:nginx-bridge nginx:v1 bash
[root@f317a0dc60ee /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:ac:11:00:02  txqueuelen 0  (Ethernet)
        RX packets 25  bytes 2191 (2.1 KiB)
        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

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

根据上述结果发现两个容器内部的网络设备相同。
再看下宿主机的网络设备,只有一个网卡如下图所示:

宿主机网络设备

最终我们可以得到container网络模式下的模型:

container

3、自定义网络-简单介绍及使用

除了使用上述四种网络模式以外,我们可以自己为容器创建网络。参考以下的shell命令:

[root@iZ2ze7sn66bchxncut8rgsZ opt]# docker network create --driver bridge my-net
3f590848cda6f56bf93cea94e768cc46da5803e721d43fcb2eed347c0d8a1ce9
[root@iZ2ze7sn66bchxncut8rgsZ opt]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
bcea3a512ca5        bridge              bridge              local
c6ec1c6228b7        host                host                local
3f590848cda6        my-net              bridge              local
25081d2267a8        none                null                local

上述结果中我们创建的my-net已经在列表中了,看下我们的网络的网段是多少:

[root@iZ2ze7sn66bchxncut8rgsZ opt]# docker network inspect my-net
[
    {
        "Name": "my-net",
        "Id": "3f590848cda6f56bf93cea94e768cc46da5803e721d43fcb2eed347c0d8a1ce9",
        "Created": "2020-09-25T14:48:46.164212085+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

上面结果里看到我们的网段是172.18.0.1,下面在看下宿主机的网段:

image.png

上图看到docker0是172.17.0.1,与我们自己创建的是不同的,下面我们使用自己的网络启动容器,并查看ip:

[root@iZ2ze7sn66bchxncut8rgsZ opt]# docker run -it --name nginx-my-net --net my-net nginx:v1 bash
[root@63e44026f6b9 /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.18.0.2  netmask 255.255.0.0  broadcast 172.18.255.255
        ether 02:42:ac:12:00:02  txqueuelen 0  (Ethernet)
        RX packets 29  bytes 2547 (2.4 KiB)
        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

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

在上面容器的网络中看到网段是172.18.0.2,这说明当前容器已经使用我们自己创建的网络了。

除了上述之外,还能手动指定网段,举个例子:

[root@iZ2ze7sn66bchxncut8rgsZ opt]# docker network create --subnet 172.19.0.0/24 mysql-net
8522866b0c686c91c27aadac015498b83d5a22632011649c81c52d0810efd4e6
[root@iZ2ze7sn66bchxncut8rgsZ opt]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
bcea3a512ca5        bridge              bridge              local
c6ec1c6228b7        host                host                local
3f590848cda6        my-net              bridge              local
8522866b0c68        mysql-net           bridge              local
25081d2267a8        none                null                local
[root@iZ2ze7sn66bchxncut8rgsZ opt]# docker network inspect mysql-net 
[
    {
        "Name": "mysql-net",
        "Id": "8522866b0c686c91c27aadac015498b83d5a22632011649c81c52d0810efd4e6",
        "Created": "2020-09-25T15:12:34.250234517+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.19.0.0/24"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

其他特性就不做过多介绍了。
参考文章:
https://blog.csdn.net/hetoto/article/details/99892743
https://blog.csdn.net/huanongying123/article/details/73556634

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/74030
 
297 次点击