8-docker网络

docker

docker网络

docker安装后默认的三种网络为none、host、bridge。
none:没有任何网路,没有任何网卡。安全性要求高并且不需要联网的应用可以使用 none 网络。
host:连接到host网络的容器共享docker宿主机的网络,容器的网络配置、hostname与docker宿主机完全一致。
bridge:桥接网络,使用最多,容器默认使用的网络。

1
2
3
4
5
~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
a245b3871ac7 bridge bridge local
4b615d9327ee host host local
05e237730870 none null local

在启动容器的时候可以使用--network=none来指定使用的网络

bridge网络

安装docker时会创建docker0的网桥,容器默认使用的都是这个

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
]# brctl show    # 需要安装bridge-utils 
bridge name bridge id STP enabled interfaces
docker0 8000.0242b1443650 no #此时是没有容器使用docker0

~]# docker run -it -d busybox
ef8acee7abadee73a33c8ded047e7f57af8aaaf85a8bd6035fb271ee8ae99fb2
~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242b1443650 no veth6e01edd

~]# docker run -it -d --name=busybox2 busybox
d96d5db03d981f4bcdf0f5374a5ca1a1dd741f40dacce82eab8e1a1bc0b68f0e
~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242b1443650 no veth2783997
veth6e01edd

veth2783997、veth6e01edd为两个网络接口,对应着两个容器的网卡

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
~]# docker network inspect bridge  
[
{
"Name": "bridge",
"Id": "e56c41006af568144839868cca47fad31c1c0f7251848bffc71621e12bd7f2ee",
"Created": "2022-10-20T01:03:46.451081072+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16", #bridge的网络配置
"Gateway": "172.17.0.1" #bridge的网络配置,该网关就是docker0
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": { #使用bridge网络的容器网络配置
"d96d5db03d981f4bcdf0f5374a5ca1a1dd741f40dacce82eab8e1a1bc0b68f0e": {
"Name": "busybox2",
"EndpointID": "395664be54909dc79a763e74ca6a4aec83d342113ddbe4c287e2a2d70fcdb67d",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
},
"ef8acee7abadee73a33c8ded047e7f57af8aaaf85a8bd6035fb271ee8ae99fb2": {
"Name": "lucid_spence",
"EndpointID": "7b780bdfdf91d7dad89978c6f0a007ec5be2d3bb283b0ce9db24078e24adfd47",
"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": {}
}
]

自定义网络

docker有三种网络驱动,bridge 、overlay 、macvlan。

自定义bridge网络

1
2
3
4
5
6
7
8
9
10
11
12
13
~]# docker network create --driver bridge test_bridge
b4a9474e46432b19582d3c7e24506aa79486aa12d938fe2f3929ba716ef3fe3e
~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
e56c41006af5 bridge bridge local
4b615d9327ee host host local
05e237730870 none null local
b4a9474e4643 test_bridge bridge local
~]# brctl show
bridge name bridge id STP enabled interfaces
br-b4a9474e4643 8000.02426345e115 no
docker0 8000.0242b1443650 no veth2783997
veth6e01edd

创建一个新的bridge网络test_bridge,对应的会创建一个新的网桥,网桥的名后段就是test_bridge的短ID。
创建的新的test_bridge网络的网络配置docker自动分配的,在创建的时候可以指定IP网段。

1
2
3
4
5
6
7
8
9
~]# docker network create --driver bridge  --subnet 172.19.0.0/16 --gateway 172.19.0.1 test_bridge_2
e3eb0f55cb6356a97189a748a3a6a821a53cf9e1583d9a574cfada2557dcc370
~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
e56c41006af5 bridge bridge local
4b615d9327ee host host local
05e237730870 none null local
b4a9474e4643 test_bridge bridge local
e3eb0f55cb63 test_bridge_2 bridge local

在创建容器的时候可以指定容器的IP,但是使用的网络必须是在创建时也指定- -subnet的。也就是使用test_bridge_2网络才可以指定容器IP,test_bridge则不行

1
2
3
4
5
~]# docker run -it -d --network=test_bridge --ip 172.19.0.2 busybox
c320bd7389697c8aaf149d0853166cc882b988c763c25f1cc053a5a6c7d8cfd1
docker: Error response from daemon: user specified IP address is supported only when connecting to networks with user configured subnets.
~]# docker run -it -d --network=test_bridge_2 --ip 172.19.0.2 busybox
09314af7bfdb84bc012aca1804d056e344db7609835040addfbd2b17f1aef8f4

不同网络容器之间通信

使用同一个bridge网络的容器之间是可以通信的,使用不同bridge网络的容器之间也可以实现通信。使用docker network connect 网络名 容器连接到指定网络,docker network connect disconnect断开指定的网络,具体的体现就是在对应的容器中多了一个对应网络的网卡。

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
~]# docker run -it -d --network=test_bridge  --name=busybox1 busybox 
17f0e3f6fd1e729b21572e5d0eef9d280e50e5327edfe9fece15764fb22743b8
~]# docker run -it -d --network=test_bridge --name=busybox2 busybox
79c883702435d5b00e6ee8ef8e4103d6025929296e9341ef5c3f98503cedb3e0
~]# docker run -it -d --network=test_bridge_2 --name=busybox3 busybox
fdd8fb26bbf26af839bae7312dd134cd7d5d94e697322d6ec61657eff4da28e9
~]# docker exec -it busybox1 sh
/ # ping busybox2 #在同一个网络中可以使用容器名进行ping
PING busybox2 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.224 ms
64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.085 ms
64 bytes from 172.18.0.3: seq=2 ttl=64 time=0.098 ms

~]# docker network connect test_bridge busybox3 #将busybox3添加一个test_bridge的网卡
~]# docker exec -it busybox3 sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
20: eth0@if21: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:13:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.19.0.2/16 brd 172.19.255.255 scope global eth0
valid_lft forever preferred_lft forever
22: eth1@if23: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:12:00:04 brd ff:ff:ff:ff:ff:ff
inet 172.18.0.4/16 brd 172.18.255.255 scope global eth1
valid_lft forever preferred_lft forever
/ # ping busybox1
PING busybox1 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.158 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.086 ms

容器之间的三种通信方式

容器之间可通过 IP,Docker DNS Server 或 joined 容器三种方式通信。

IP通信

属于同一个网络的容器之间是可以通信的。不同网络之间通过docker network connect 网络名 容器实现通信。

Docker DNS Server

docker内置了DNS服务,在IP通信的情况下可以使用DNS服务进行通信,busybox1与busybox2,以及将busybox3添加到test_bridge网络后,容器之间使用容器名就可以ping通。
Docker DNS Server只能是在自定义网络中使用,默认的bridge网络无法使用DNS

joined容器

使多个容器共享一个网络栈,共享网卡和配置信息。

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
~]# docker run -it -d --name=test_join busybox
578c4ad593d44212bf8180120ff6a5d41b64a8ec60b89ccd6be746baafc474a9
~]# docker run -it -d --network=container:test_join --name=test_join_2 busybox
9b4f485357a3e04a41fd1b883ffcc1ef381fb42b6fc3b3d01018c0fa8c46d584

~]# docker exec -it test_join sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
24: eth0@if25: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever

~]# docker exec -it test_join_2 sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
24: eth0@if25: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever

可以发现test_join与test_join_2的网络配置是相同的。

容器与外界通信

容器访问外界

例如容器内ping 百度,以下是通信过程。

  1. ping www.baidu.com,容器网卡发包
  2. docker0收到包,交给NAT处理
  3. NAT将源地址转换成宿主机网卡的IP
  4. ping包从宿主机的网卡发出到达百度

外界访问容器

外部想要访问容器,容器需要将端口映射到宿主机的端口,通过docker run -p 宿主机端口:容器端口实现。外部访问时访问宿主机的端口也就是访问了容器的端口
每一个映射的端口,host 都会启动一个 docker-proxy 进程来处理访问容器的流量。

  1. docker-proxy 监听映射后宿主的端口
  2. 当外界访问宿主机端口时,docker-proxy转发给容器
  3. 容器响应请求并返回结果