docker网络
docker网络
Docker安装时会自动的在Docker host上创建三种网络,我们可以使用docker network ls查看。这 三种网络分别是none网络、host网络、bridge网络,bridge网络是我们在创建容器时默认使用的网络
[root@node1 ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 794128dd47c4 bridge bridge local b0bf0ec21aa8 host host local a8d37488b915 none null local [root@node1 ~]#
none网络
故名思议,none网络就是什么都没有的网络。在这个网络下的容器除了lo,没有其他任何网卡。容器创建时,可以通过-- network=none指定使用none网络,通过下面这个示例可以看出,创建容器时指定容器网络类型为none时,容器内只有一个lo网络。
[root@docker ~]# docker pull busybox [root@docker ~]# docker run --name cygalaxy -it --rm --network=none busybox:latest / # 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 foreve
none网络是个封闭的网络,使用了这种网络类型的容器无法在网络层被访问。封闭意味着隔离,一些对安全性要求高并且不需要 联网的应用可以使用none网络。比如某个容器的唯一用途是生成随机密码,就可以放到none网络中避免密码被窃取。
host网络
使用host网络的容器共享Docker host的网络栈,容器的网络配置与Docker host完全一样。可以通过--network=host指定使用 host网络。可以通过以下示例看到,创建容器指定容器网络为host时,容器直接共享了Docker host的网络,能够获取到Docker host 的网络信息。
[root@docker ~]# docker run --name cygalaxy -it --rm --network=host busybox:latest / # ip a 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000 link/ether 00:0c:29:d4:97:23 brd ff:ff:ff:ff:ff:ff inet 172.25.0.100/16 brd 172.25.255.255 scope global noprefixroute ens33 valid_lft forever preferred_lft forever inet6 fe80::a246:4804:35d4:bb91/64 scope link noprefixroute valid_lft forever preferred_lft forever
直接使用Docker host的网络最大的好处就是性能,如果容器对网络传输效率有较高要求,则可以选择host网络。当然不便之处就 是牺牲一些灵活性,比如要考虑端口冲突问题,Docker host上已经使用的端口就不能再用了。
这次我们使用httpd镜像创建容器,如下示例,可以看出容器中的80端口已经绑定到Docker host的 网络上,如果Docker host自身也有80端口的应用,那么就会与容器的80产生冲突。[root@docker ~]# docker run --name httpd -itd --network=host httpd a3dbbf169f8f2c68792658c75bf7d5c0c096a382214fcb881b547ef944167184 [root@docker ~]# ss -tpln | grep 80 LISTEN 0 128 :::80 :::* users:(("httpd",pid=10632,fd=4)...
Bridge网络
Docker安装时会创建一个命名为docker0的linux bridge。如果不指定--network,创建的容器默认 都会挂到docker0上。如下示例,docker0上没有任何其他网络设备。
[root@docker ~]# yum install bridge-utils [root@docker ~]# brctl show bridge name bridge id STP enabled interfaces docker0 8000.02425f2ee17b no virbr0 8000.5254008d8bec yes virbr0-nic
我们新创建一个容器,一个新的网络接口veth98c678e被挂到了docker0上,veth98c678e就是新创建容器的虚 拟网卡。由于在创建容器的时候使用了--rm参数,退出容器时会自动的删除容器,需要开启多个终端进行示例操作。
[root@docker ~]# docker run --name cygalaxy -it --rm busybox / # ip a 6: eth0@if7: <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
容器有一个网卡eth0@if7。实际上eth0@if7和veth98c678e是一对veth pair。veth pair是一种成对出现的特殊网络 设备,可以把它们想象成由一根虚拟网线连接起来的一对网卡,网卡的一头(eth0@if7)在容器中,另一头 (veth98c678e)挂在网桥 docker0 上,其效果就是将eth0@if7也挂在了 docker0 上
我们还看到eth0@if7已经配置了IP:172.17.0.2,让我们通过docker network inspect bridge看一下 bridge网络的配置信息:[root@docker ~]# docker network inspect bridge ...... "Config": [ { "Subnet": "172.17.0.0/16", "Gateway": "172.17.0.1" .........
原来bridge网络配置的subnet就是172.17.0.0/16,并且网关是172.17.0.1。容器创建时,Docker会 自动从172.17.0.0/16中分配一个IP,这里16位的掩码保证有足够多的IP可以供容器使用。
自定义bridge网络
之前我们所使用的网络都是安装Docker时默认生成的网络。我们可通过bridge驱动创建类似前面默认的 bridge 网络,示例如下,网络名称为cygalaxy123,类型为bridge,地址池为172.19.0.0/16,网关为172.19.0.1。
[root@docker ~]# docker network create --driver bridge --subnet 172.19.0.0/16 --gateway 172.19.0.1 cygalaxy123 [root@docker ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 7db6a96072e6 cygalaxy123 bridge local [root@docker ~]# ip a 8: br-7db6a96072e6: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether 02:42:af:17:3b:7b brd ff:ff:ff:ff:ff:ff inet 172.19.0.1/16 brd 172.19.255.255 scope global br-7db6a96072e6 valid_lft forever preferred_lft forever
创建新的容器,指定使用cygalaxy123网络,还可以使用--ip指定容器所使用的ip,这个ip要是 cygalaxy123地址池中的ip。如果不指定ip,那么cygalaxy123会自动给容器分配ip。
[root@docker ~]# docker run --name galaxycy -it --rm --network=cygalaxy123 --ip 172.19.0.100 busybox / # ip a 9: eth0@if10: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:ac:13:00:64 brd ff:ff:ff:ff:ff:ff inet 172.19.0.100/16 brd 172.19.255.255 scope global eth0 valid_lft forever preferred_lft foreve
如果创建一个容器a1,使用的默认bridge网络,再创建第二个容器a2,使用的cygalaxy123网络,这种情况下两 个容器之间是不能够直接通讯的。只有指定了相同的网络的容器才能够互通。其实我们可以为容器指定多个网络,实现 容器之间的通讯,示例如下,创建新的容器,指定cygalaxy123网络,使用connect参数为该容器添加默认bridge网 络,或者其他的bridge网络。
[root@docker ~]# docker run --name a1 -it --rm busybox / # ip a 13: eth0@if14: <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 [root@docker ~]# docker run --name a2 -itd --network=cygalaxy123 --ip 172.19.0.100 busybox [root@docker ~]# docker network connect bridge a2 [root@docker ~]# docker exec -it a2 sh / # ip a 15: eth0@if16: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:ac:13:00:64 brd ff:ff:ff:ff:ff:ff inet 172.19.0.100/16 brd 172.19.255.255 scope global eth0 valid_lft forever preferred_lft forever 17: eth1@if18: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff inet 172.17.0.3/16 brd 172.17.255.255 scope global eth1 valid_lft forever preferred_lft foreve
docker容器之间的访问方式
容器之间访问可以使用以下方式
1、基于IP地址进行访问
2、基于容器名进行访问
3、多个容器共享同一个网络协议栈
注意:只有在同一个Docker网络中的容器才能够互相通讯;只有使用了默认的Bridge网络的容器是 无法使用基于容器名的方式进行容器互访的。
基于IP地址进行访问
创建一个新的容器mycy_1,使用cygalaxy123网络,容器获取的ip为172.19.0.2
[root@docker ~]# docker run --name mycy_1 -it --rm --network=cygalaxy123 busybox / # ip a 19: eth0@if20: <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
再创建第二个容器mycy_2,使用的也是cygalaxy123网络,直接ping第一个容器mycy_1的IP,示例如下。
[root@docker ~]# docker run --name mycy_2 -it --rm --network=cygalaxy123 busybox / # ping 172.19.0.2 PING 172.19.0.2 (172.19.0.2): 56 data bytes 64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.060 ms 64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.062 ms
通过以上两个示例得知,在同一个网络中的容器,是可以使用IP进行互相访问的。
基于容器名进行访问
通过IP访问容器虽然满足了通信的需求,但还是不够灵活。因为我们在部署应用之前可能无法确定IP,部署之后再 指定要访问的IP会比较麻烦。对于这个问题,可以通过Docker自带的DNS服务解决。
从Docker 1.10版本开始,Docker daemon实现了一个内嵌的DNS server,使容器可以直接通过“容器名”通 信。方法很简单,只要在启动时用--name为容器命名就可以了,示例如下。
[root@docker ~]# docker run --name cy1 -itd --network=cygalaxy123 busybox [root@docker ~]# docker run --name cy2 -it --network=cygalaxy123 busybox / # ping cy1 PING cy1 (172.19.0.2): 56 data bytes 64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.046 ms 64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.045 ms 64 bytes from 172.19.0.2: seq=2 ttl=64 time=0.051 ms
通过以上示例得知,创建容器时,使用--name定义容器名称,当容器启动时,Docker daemon会把容器名与容 器获取的IP进行绑定,写入到Docker DNS中,这样容器之间访问就可以基于容器名实现了,如果容器停止了,该容器 所对应的DNS信息就会从Docker DNS中删除。使用Docker DNS有个限制,只能在新创建的bridge网络中使用。
joined容器
Joined(联合)容器是另一种实现容器间通信的方式。joined容器非常特别,它可以使两个或多个容器 共享一个网络栈,共享网卡和配置信息,joined容器之间可以通过127.0.0.1直接通信。请看下面的例 子:
[root@docker ~]# docker run --name cy3 -itd --network=cygalaxy123 busybox [root@docker ~]# docker run --name cy4 -it --rm --network=container:cy3 busybox / # ping cy3 PING cy3 (172.19.0.3): 56 data bytes 64 bytes from 172.19.0.3: seq=0 ttl=64 time=0.201 ms 64 bytes from 172.19.0.3: seq=1 ttl=64 time=0.039 ms 64 bytes from 172.19.0.3: seq=2 ttl=64 time=0.036 ms
使用joined容器的方式实现容器间的通讯,需要注意的是两个容器之间的应用端口容易发生冲突, 两个容器共享一个网络栈,那么容器中的应用在运行时,绑定的IP也是一样。
容器访问外部
1、 容器int_1发送Ping报文包:172.17.0.3 > www.baidu.com。
2、docker0收到报文,发现是发送到外网的,交给NAT处理。
3、NAT将源地址换成ens36的IP:192.168.31.106 > www.baidu.com。
4、Ping包从ens36发送出去,到达 www.baidu.com。 通过NAT,docker实现了容器对外网的访问。
外部访问容器
如果想实现外部访问容器,可使用host网络,容器共享Docker host网络栈,就可以实现外部访问容 器。还有一种方法也是我们最常用的使用端口映射。
Docker可将容器对外提供服务的端口映射到Docker host的某个端口,外网通过该端口访问容器。容 器启动时通过-p参数映射端口,示例如下:
[root@docker ~]# docker run --name web1 -it -d -p 80:80 httpd 4d6f098217e537ff9696801b646c647fa8320c09b68677d1cd59c9977fc9683d [root@docker ~]# curl http://127.0.0.1:80 <html><body><h1>It works!</h1></body></html>
总结
1.none网络是个封闭的网络,使用了这种网络类型的容器无法在网络层被访问。
2.使用host网络的容器共享Docker host的网络栈,容器的网络配置与host完全一样。
3. 使用Docker默认的bridge网络创建容器,是无法使用容器名进行容器互访的,而使用自定义的bridge 网络创建容器,是可以使用容器名进行容器互访的。
4. 只有在同一个网络下的容器才能够互相访问。 华育智远
原文地址:https://blog.csdn.net/czzwa/article/details/142358899
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!