五、Docker网络管理
转载自:https://www.cnblogs.com/dcz2015/p/12463862.html
一、Docker网络的介绍
Docker 通过Network Namespace 的方式,为每一个容器建立了独立的网络,形成了完全与宿主机隔离的环境。
安装 Docker 后,会自动创建三种默认的网络,分别为 bridge,host,none。。
可以使用 docker network ls 命令进行查看:
1
2
3
4
5
|
[root@TBEARZ206458 ~] # docker network ls NETWORK ID NAME DRIVER SCOPE 1934a5d2941a bridge bridge local a8e866affd79 host host local 9b21f21fd421 none null local |
① bridge,即桥接网络,在安装 docker 后会创建一个桥接网络,该桥接网络的名称为 docker0。我们可以通过下面两条命令去查看该值。
可以通过 docker network inspect bridge 进行网络的查看
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
|
[root@TBEARZ206458 ~] # docker network inspect bridge [ { "Name" : "bridge" , "Id" : "1934a5d2941a18450a31505487c205c5004a140fb85340aee3824efc368b0356" , "Created" : "2020-03-02T09:36:01.469784644+08:00" , "Scope" : "local" , "Driver" : "bridge" , "EnableIPv6" : false , "IPAM" : { "Driver" : "default" , "Options" : null , "Config" : [ { "Subnet" : "172.17.0.0/16" , "Gateway" : "172.17.0.1" } ] }, "Internal" : false , "Attachable" : false , "Ingress" : false , "ConfigFrom" : { "Network" : "" }, "ConfigOnly" : false , "Containers" : {}, "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" : {} } ] |
使用ifconfig命令,可以查看到docker0网络的信息
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
|
[root@TBEARZ206458 ~] # ifconfig docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255 ether 02:42:2a:9f:77:8a txqueuelen 0 (Ethernet) RX packets 25809 bytes 13495463 (12.8 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 30103 bytes 17251842 (16.4 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 103.39.213.253 netmask 255.255.255.192 broadcast 103.39.213.255 ether 00:0c:29:ed:e0:2d txqueuelen 1000 (Ethernet) RX packets 12367111 bytes 8008281549 (7.4 GiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 2096342 bytes 328067827 (312.8 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 10.39.213.253 netmask 255.255.255.192 broadcast 10.39.213.255 ether 00:0c:29:ed:e0:37 txqueuelen 1000 (Ethernet) RX packets 1307344 bytes 80354955 (76.6 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 1312 bytes 78750 (76.9 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 40 bytes 10068 (9.8 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 40 bytes 10068 (9.8 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 |
默认情况下, Docker 启动时会在宿主机上架设一个名为docker0的虚拟网络,用来连接宿主机与容器。既然容器的网络是以独立隔离的形式存在的,那么Docker 又是如何利用docker0 来实现容器与宿主机。
容器启动时, Docker 会把容器内通过Network Namespace 建立的独立网络,通过VethPair 连接到docker0所在的虚拟网络上。
默认情况下,我们创建一个新的容器都会自动连接到 bridge 网络。
以下命令是等价的
docker container run -it -d --name defaultcontainer1 centos
和
docker container run -it -d --network bridge --name defaultcontainer1 centos
例如创建一个新的容器,然后查看一下bridge
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
|
[root@TBEARZ206458 ~] # docker container run -it -d --name defaultcontainer1 centos c7d0722065660b024789c7757dfc8fa3395c2167d3ba5ed90aee5f343bf4dde7 [root@TBEARZ206458 ~] # docker network inspect bridge [ { "Name" : "bridge" , "Id" : "1934a5d2941a18450a31505487c205c5004a140fb85340aee3824efc368b0356" , "Created" : "2020-03-02T09:36:01.469784644+08:00" , "Scope" : "local" , "Driver" : "bridge" , "EnableIPv6" : false , "IPAM" : { "Driver" : "default" , "Options" : null , "Config" : [ { "Subnet" : "172.17.0.0/16" , "Gateway" : "172.17.0.1" } ] }, "Internal" : false , "Attachable" : false , "Ingress" : false , "ConfigFrom" : { "Network" : "" }, "ConfigOnly" : false , "Containers" : { "c7d0722065660b024789c7757dfc8fa3395c2167d3ba5ed90aee5f343bf4dde7" : { "Name" : "defaultcontainer1" , "EndpointID" : "0fe7699d6fa21d02a3179546a23594cff016b9530128461a69152dc27c99a5db" , "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" : {} } ] |
备注:如果出现bash: ifconfig: command not found,可以执行如下操作:
1
|
yum install net-tools |
② host
host 网络,容器可以直接访问主机上的网络。
1
|
$ docker run -it --network host --rm busybox /bin/sh |
③ none
none 网络,容器中不提供其它网络接口。none 网络的容器创建之后还可以自己 connect 一个网络,比如使用 docker network connet bridge 容器名
可以将这个容器添加到 bridge 网络中。
1
|
$ docker run -it --nerwork none --rm busybox /bin/sh |
二、网络访问
上面的图表明了,docker容器-宿主机-外部之间的沟通方式,首先容器可以通过docker0对外部进行访问,但是外部通过docker0必须之后转发给具体的哪个容器,这个比较简单的解决方法就是通过绑定端口方式。
I.绑定端口
我们在启动容器的时候,可以通过 (docker run -d -p nginx)-p 指定绑定的端口。
1
2
3
4
5
|
[root@TBEARZ206458 ~] # docker container run -itd --name mydotnet -p 8080:80 centosdotent:1.0.0 f6a624c5d8ac79eb964dd702774e41655da1930d9eaa83d01b9a909b95c0abd6 [root@TBEARZ206458 ~] # docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f6a624c5d8ac centosdotent:1.0.0 "dotnet DotnetWebDem…" 20 seconds ago Up 18 seconds 5000/tcp, 0.0.0.0:8080->80/tcp mydotnet |
上面的命令执行之后,就可以通过宿主机的8080端口,访问到容器的80端口了。
此外当容器需要绑定多个端口的时候,可以使用多次 -p <ip>:<hport>:<cport>这种参数形式,绑定多个。
II.容器连接
使用端口绑定可以达到外部对宿主机内部容器访问的目的,但是有时候还需要处理容器之间的连接,此时就需要用到【容器连接】。
一个容器中运行的应用程序,也需要与运行在另外一个容器中的应用程序,通过网络进行数据交换。
要设置容器间通信,我们可以通过在创建容器时携带一link 参数来实现,参数的使用形式是 一link <c ontainer>
举例:创建一个dotnet站点的容器并连接一个mysql的容器
创建一个mysql容器,然后连接它
1
2
|
[root@TBEARZ206458 ~] # docker run -d -p 8082:80 -p 443:443 --name dotnet --link mysql centosdotent:1.0.0 74c7ed3616ea2930679a91940a60c111601b448f8cf438334f8b92cadf50cd8e |
设置容器间通信的参数,只需要指定被连接的容器,并不需要指明被连接容器的端口,在创建和启动被连接容器时,也不需要通过-P 或 -p 参数来映射端口。
这就保证了被连接容器的端口只在容器间的通信中使用,不会被暴露在外网中,也不会被其他容器访问到。
用了上面方法的连接的mysql容器,在dotnet容器中只要在使用mysql的时候使用连接的名字例如把Host改成mysql就可以连接mysql服务了。