Docker学习笔记(三)

Docker网络介绍

Docker网络共分为四种模式,如下图,从左到右为:

  • None(Close) container 封闭式网络模式
  • Bridged container 桥接式网络模式
  • Container(join) container 联合挂载式网络模式
  • Host(open) container 开放式(主机)网络模式

Docker network

(图片来源于网络)

注:这个图很重要,下面具体介绍每种模式的时候可以对照学习

我们也可以通过以下命令查看:

1
2
3
4
5
[root@ramon ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
c8b12c57ad04 bridge bridge local
57097e22d8dc host host local
4b0f55f2b211 none null local

下面来依次介绍每种模式。

None网络模式

介绍:none网络模式下不会对容器进行网络配置,只有lo回环网络

配置:在执行docker run的时候添加--network none的选项

特点:封闭的网络保证了容器的安全性,适用于一些无需联网的场景,比如备份、进城诊断等。

示例

1
2
3
4
5
6
7
8
9
# 1.启动一个none网络模式的docker
[root@ramon ~]# docker run -it --name centos-none --network none centos /bin/bash
# 2.查看网络配置(只有lo回环地址)
[root@ddc8466a57f2 /]# 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
[root@ddc8466a57f2 /]#

Bridge网络模式

介绍:docker在安装的时候创建了一个名为docker0的虚拟网桥,启动的Docker容器会连接到这个虚拟网桥上,然后docker0通过NAT与宿主机上网卡之间进行数据转换,到达容器连接网络的目的。

配置:不用配置,默认的网络模式

特点:桥接模式为容器提供一个独立的网络栈,保证了容器内独立的网络环境,实现了网络隔离,适用于大多数需要独立网络的场景。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 1.查看网桥(docker0)
[root@ramon ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242ba5cd331 no
# 2.查看网络配置
[root@ramon ~]# 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
# 服务器内网地址
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1454 qdisc pfifo_fast state UP group default qlen 1000
link/ether 52:54:00:63:f3:eb brd ff:ff:ff:ff:ff:ff
inet 10.8.123.130/16 brd 10.8.255.255 scope global eth0
valid_lft forever preferred_lft forever
# docker0
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:ba:5c:d3:31 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
# 3.开启两个桥接模式容器
[root@ramon ~]# docker run -d --name nginx01 nginx
4b1e771654cc50bcd3fad7da752e3e2d4809804443c17f99b925cc957a2ff38c
[root@ramon ~]# docker run -d --name nginx02 nginx
84073adfc3f99614e5c24de741e5727a9c088f2d3b10bc24115b2c7f4522db15
# 4.可以看到两个新的网络接口被挂载到了docker0上
[root@ramon ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242ba5cd331 no veth9e758c2
vethe04773c
# 5.通过inspct可以查看具体挂载信息
[root@ramon ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
c8b12c57ad04 bridge bridge local
57097e22d8dc host host local
4b0f55f2b211 none null local
[root@ramon ~]# docker network inspect c8b12c57ad04

Container网络模式

介绍:指定一个已存在的容器共享一个网络,自己不会配置新的网卡

配置:在执行docker run的时候添加--network container:$CONTAINER_ID的选项

特点:与其他容器共享一个网络配置,两个容器可以直接通过lo网卡通信,适用于容器间大量通信且需要保证通信质量的情况。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 1.运行一个centos容器
[root@ramon ~]# docker run -d --name centos01 centos /bin/bash -c "while true; do sleep 100; done"
aaa2d51b07d8a31072d644f5ba99d609dc84debd3bedfc0fa671ac601838ce37
# 2.查看网络配置
[root@ramon ~]# docker exec -it centos01 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
70: eth0@if71: <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
# 3.查看centos0的容器id
[root@ramon ~]# docker ps
CONTAINER ID IMAGE COMMAND
aaa2d51b07d8 centos "/bin/bash -c 'while…"
# 4.以联合挂载模式启动第二个容器
[root@ramon ~]# docker run -it --name centos02 --network container:aaa2d51b07d8 centos /bin/bash
# 5.查看网络配置(与centos01一样)
[root@aaa2d51b07d8 /]# 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
70: eth0@if71: <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

##Host网络模式

介绍:与宿主机共用同一个网络,网络配置相同

配置:在执行docker run的时候添加--network host的选项

特点:与宿主机共用一个网络,少了NAT转发的过程,速度加快,但会占用宿主机的端口

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 1.查看宿主机网络配置
[root@ramon ~]# 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
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1454 qdisc pfifo_fast state UP group default qlen 1000
link/ether 52:54:00:63:f3:eb brd ff:ff:ff:ff:ff:ff
inet 10.8.123.130/16 brd 10.8.255.255 scope global eth0
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:ba:5c:d3:31 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@ramon ~]#
# 2.运行一个host网络模式的docker
[root@ramon ~]# docker run --name centos_host -it --network host centos /bin/bash
Unable to find image 'centos:latest' locally
latest: Pulling from library/centos
6910e5a164f7: Pull complete
Digest: sha256:4062bbdd1bb0801b0aa38e0f83dece70fb7a5e9bce223423a68de2d8b784b43b
Status: Downloaded newer image for centos:latest
# 3.查看docker内的网络配置(与宿主机完全一样)
[root@ramon /]# 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
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1454 qdisc pfifo_fast state UP group default qlen 1000
link/ether 52:54:00:63:f3:eb brd ff:ff:ff:ff:ff:ff
inet 10.8.123.130/16 brd 10.8.255.255 scope global eth0
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:ba:5c:d3:31 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

容器互联

前面我们已经知道了默认的网桥docker0,但是在这个默认配置上创建的这些容器之间只能通过ip互相通信,不能直接通过容器名通信,这给我们集群配置自动化带来一定的复杂性(配置host或者配置静态ip都需要一些额外的操作和局限性)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 1.拉起两个容器
[root@ramon ~]# docker run -d -P --name tomcat01 tomcat
16e611f0334f9cc3ce7839e0c6bc865ba13828f6ae2169a916a88426cb7bf990
[root@ramon ~]# docker run -d -P --name tomcat02 tomcat
31a445618e9f31b50993fdfad2ff88b73d9c84edabc9ebab015e85ae9c0f1cfd
# 2.查看tomcat01的ip信息
[root@ramon ~]# docker inspect -f '{{json .NetworkSettings.Networks.bridge.IPAddress}}' 16e611f0334f
"172.17.0.2"
# 3.tomcat02是可以ping通tomcat01的
[root@ramon ~]# docker exec -it 31a445618e9f 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.090 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.073 ms
^C
--- 172.17.0.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.073/0.081/0.090/0.012 ms
# 4.tomcat02直接ping tomcat01的容器名是失败的
[root@ramon ~]# docker exec -it 31a445618e9f ping tomcat01
ping: tomcat01: Name or service not known
[root@ramon ~]#

针对需求我们有如下方案:

link链接

在调用docker run的时候我们增加--link的选项,可以将新开始的容器之前已有的容器绑定,之后就可以接直接通过ping $docker_name的方式进行网络互联了,如下图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1.创建link到tomcat01的容器tomcat03
[root@ramon ~]# docker run -P -d --name tomcat03 --link tomcat01 tomcat
ade641d7d4a186d1262e206903106c3ee902d670a5a041d149cc8d48821492e5
# 2.容器tomcat03可以直接ping容器名
[root@ramon ~]# docker exec -it tomcat03 ping tomcat01
PING tomcat01 (172.17.0.2) 56(84) bytes of data.
64 bytes from tomcat01 (172.17.0.2): icmp_seq=1 ttl=64 time=0.127 ms
64 bytes from tomcat01 (172.17.0.2): icmp_seq=2 ttl=64 time=0.060 ms
^C64 bytes from tomcat01 (172.17.0.2): icmp_seq=3 ttl=64 time=0.057 ms
64 bytes from tomcat01 (172.17.0.2): icmp_seq=4 ttl=64 time=0.056 ms
^C
--- tomcat01 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3ms
rtt min/avg/max/mdev = 0.056/0.075/0.127/0.030 ms

但是这种方式现在并不推荐,它的原理就是修改了/ect/hosts文件,进行了地址映射,而且只是单向绑定,如下图:

1
2
3
4
5
6
7
8
9
10
11
[root@ramon ~]# docker exec -it tomcat03 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 tomcat01 671f04cf31bf
172.17.0.4 ade641d7d4a1
[root@ramon ~]# docker exec -it tomcat01 ping tomcat03
ping: tomcat03: Name or service not known

另一种更好的处理方式就是自定义网络了。

自定义网络

自定义网络即我们使用docker network自己创建一个网络,命令如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 参数
[root@ramon ~]# 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@ramon ~]# docker network create --help
Usage: docker network create [OPTIONS] NETWORK
Create a network
Options:
--attachable Enable manual container attachment
--aux-address map Auxiliary IPv4 or IPv6 addresses used by Network driver (default map[])
--config-from string The network from which copying the configuration
--config-only Create a configuration only network
-d, --driver string Driver to manage the Network (default "bridge")
--gateway strings IPv4 or IPv6 Gateway for the master subnet
--ingress Create swarm routing-mesh network
--internal Restrict external access to the network
--ip-range strings Allocate container ip from a sub-range
--ipam-driver string IP Address Management Driver (default "default")
--ipam-opt map Set IPAM driver specific options (default map[])
--ipv6 Enable IPv6 networking
--label list Set metadata on a network
-o, --opt map Set driver specific options (default map[])
--scope string Control the network's scope
--subnet strings Subnet in CIDR format that represents a network segment

创建一个自己的自定义网络示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 1.创建一个网络
# -d bridge 网络模式
# --subnet 192.168.0.0/24 子网
# --gateway 192.168.0.1 网关地址
[root@ramon ~]# docker network create -d bridge --subnet 192.168.0.0/24 --gateway 192.168.0.1 tomcat_net
ef9023a99fefab02bcdf4461b6fc2b7e800f490ba718186e95bff573a1a1b269
# 2.查看docker网络
[root@ramon ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
c8b12c57ad04 bridge bridge local
57097e22d8dc host host local
4b0f55f2b211 none null local
ef9023a99fef tomcat_net bridge local
# 3.查看新增网桥
[root@ramon ~]# brctl show
bridge name bridge id STP enabled interfaces
br-ef9023a99fef 8000.02427c796a5e no
docker0 8000.0242ba5cd331 no veth5fa92d1
veth8767ea2
vethc4a5d72
[root@ramon ~]#

创建完成后,我们来查看我们的实际测试情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 1.创建指定network的容器
[root@ramon ~]# docker run -d -P --name tomcat01 --net tomcat_net tomcat
a995d63caecdb3d97bbd27c5d4e65ddc81429e06dee9cd032ee4179959803723
[root@ramon ~]# docker run -d -P --name tomcat02 --net tomcat_net tomcat
c964f8284dc265656b471f91ed459c265e42ac51158e6e5d0250ba3c23ef2bcb
# 2.验证网络联通
[root@ramon ~]# docker exec -it tomcat01 ping tomcat02
PING tomcat02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat02.tomcat_net (192.168.0.3): icmp_seq=1 ttl=64 time=0.066 ms
64 bytes from tomcat02.tomcat_net (192.168.0.3): icmp_seq=2 ttl=64 time=0.104 ms
^C
--- tomcat02 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.066/0.085/0.104/0.019 ms、
# 3.使用inspect也能看到自定义网络下挂载的容器及网络信息
[root@ramon ~]# docker network inspect tomcat_net
[{
...
"Containers": {
"a995d63caecdb3d97bbd27c5d4e65ddc81429e06dee9cd032ee4179959803723": {
"Name": "tomcat01",
"EndpointID": "0afb96d6e4639b0fa7943a3684b3928bc643d5d0e15c05ab7838f57f4123fe3a",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/24",
"IPv6Address": ""
},
"c964f8284dc265656b471f91ed459c265e42ac51158e6e5d0250ba3c23ef2bcb": {
"Name": "tomcat02",
"EndpointID": "7830023b269fc1cdca141de39437096810d794223ccfb9144a416d2d85beeb33",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/24",
"IPv6Address": ""
}
},
...
}]

当然,自定义网络的好处不只有这个,因为我们是可以自定义网段的,那么可以很分辨的对不同的集群分配不同的网段,这样可以实现集群之间的网络隔离,不过集群之间也是要相互链接的,这时候可以使用到我们的docker network connect命令。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 参数解析
[root@ramon ~]# docker network connect --help
Usage: docker network connect [OPTIONS] NETWORK CONTAINER
Connect a container to a network
Options:
--alias strings Add network-scoped alias for the container
--driver-opt strings driver options for the network
--ip string IPv4 address (e.g., 172.30.100.104)
--ip6 string IPv6 address (e.g., 2001:db8::33)
--link list Add link to another container
--link-local-ip strings Add a link-local address for the container
# 示例
# 1.运行一个默认网络的容器
[root@ramon ~]# docker run -d -P --name tomcat-bridge0 tomcat
85033c1803d91383ed94f65ded18b1feb4952d08d587cd52d49a46e62ce934f7
# 2.这时候是无法直接使用容器名ping通的
[root@ramon ~]# docker exec -it tomcat-bridge0 ping tomcat01
ping: tomcat01: Name or service not known
# 3.使用docker network connect连接
[root@ramon ~]# docker network connect tomcat_net tomcat-bridge0
# 4.可以ping通了
[root@ramon ~]# docker exec -it tomcat-bridge0 ping tomcat01
PING tomcat01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat01.tomcat_net (192.168.0.2): icmp_seq=1 ttl=64 time=0.067 ms
64 bytes from tomcat01.tomcat_net (192.168.0.2): icmp_seq=2 ttl=64 time=0.085 ms
^C
--- tomcat01 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1ms

docker network connect的原理就是给这个容器在对应网段新分配了一个ip,这个容器有了两个网络配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
[root@ramon ~]# docker network inspect tomcat_net
[{
...
"ConfigOnly": false,
"Containers": {
"85033c1803d91383ed94f65ded18b1feb4952d08d587cd52d49a46e62ce934f7": {
"Name": "tomcat-bridge0",
"EndpointID": "301b2ec784a20a1a1bce16dec4a65aef69a7c27c06af70f86e31e4c467420745",
"MacAddress": "02:42:c0:a8:00:04",
"IPv4Address": "192.168.0.4/24",
"IPv6Address": ""
},
"a995d63caecdb3d97bbd27c5d4e65ddc81429e06dee9cd032ee4179959803723": {
"Name": "tomcat01",
"EndpointID": "0afb96d6e4639b0fa7943a3684b3928bc643d5d0e15c05ab7838f57f4123fe3a",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/24",
"IPv6Address": ""
},
"c964f8284dc265656b471f91ed459c265e42ac51158e6e5d0250ba3c23ef2bcb": {
"Name": "tomcat02",
"EndpointID": "7830023b269fc1cdca141de39437096810d794223ccfb9144a416d2d85beeb33",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/24",
"IPv6Address": ""
}
},
...
}]
[root@ramon ~]# docker inspect tomcat-bridge0
[{
...
"NetworkSettings": {
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "c8b12c57ad040772a2f082ef4c941578395381da41d496e77ff140d5203bb352",
"EndpointID": "191386f5d5ec24a4803ca61546227bfa93873e4457be356311d9f399700afb1f",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
},
"tomcat_net": {
"IPAMConfig": {},
"Links": null,
"Aliases": [
"85033c1803d9"
],
"NetworkID": "ef9023a99fefab02bcdf4461b6fc2b7e800f490ba718186e95bff573a1a1b269",
"EndpointID": "301b2ec784a20a1a1bce16dec4a65aef69a7c27c06af70f86e31e4c467420745",
"Gateway": "192.168.0.1",
"IPAddress": "192.168.0.4",
"IPPrefixLen": 24,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:c0:a8:00:04",
"DriverOpts": {}
}}}
...
}]

参考文献

狂神B站Docker视频

Docker 网络模式详解

docker的五种网络模式总结

-------------本文结束,感谢您的阅读-------------