社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  docker

Docker学习(七)网络

我犟不过你 • 6 年前 • 453 次点击  

一、网络

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