一、网络
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 了技术:
由上面的步骤我们能够推断出docker 容器的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网络模式的模型。
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网络模式下的模型:
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,下面在看下宿主机的网段:
上图看到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