五、Docker网络管理
一、Docker网络的介绍
Docker 通过Network Namespace 的方式,为每一个容器建立了独立的网络,形成了完全与宿主机隔离的环境。
安装 Docker 后,会自动创建三种默认的网络,分别为 bridge,host,none。。
可以使用 docker network ls 命令进行查看:
[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 进行网络的查看
[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网络的信息
[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
[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,可以执行如下操作:
yum install net-tools
② host
host 网络,容器可以直接访问主机上的网络。
$ docker run -it --network host --rm busybox /bin/sh
③ none
none 网络,容器中不提供其它网络接口。none 网络的容器创建之后还可以自己 connect 一个网络,比如使用 docker network connet bridge 容器名
可以将这个容器添加到 bridge 网络中。
$ docker run -it --nerwork none --rm busybox /bin/sh
二、网络访问
上面的图表明了,docker容器-宿主机-外部之间的沟通方式,首先容器可以通过docker0对外部进行访问,但是外部通过docker0必须之后转发给具体的哪个容器,这个比较简单的解决方法就是通过绑定端口方式。
我们在启动容器的时候,可以通过 (docker run -d -p nginx)-p 指定绑定的端口。
[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>这种参数形式,绑定多个。
使用端口绑定可以达到外部对宿主机内部容器访问的目的,但是有时候还需要处理容器之间的连接,此时就需要用到【容器连接】。
一个容器中运行的应用程序,也需要与运行在另外一个容器中的应用程序,通过网络进行数据交换。
要设置容器间通信,我们可以通过在创建容器时携带一link 参数来实现,参数的使用形式是 一link <c ontainer>
举例:创建一个dotnet站点的容器并连接一个mysql的容器
创建一个mysql容器,然后连接它
[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服务了。