平常开发中,接触最先的是虚拟机(vmware, virtualbox)里的网络模型。而在docker下的网络模型(networkdriver)是docker架构中处理网络虚拟化的重要部分,主要默认的能够看到有如下三种。html
root@volvo:/etc# docker network ls NETWORK ID NAME DRIVER SCOPE 7235d2d26f6f bridge bridge local 7ea4e817d5fd host host local 1a445ef4688b none null local
另外docker
还有Container
、overlay
和macvlan
。overlay
主要是基于多个docker host
之间(通常是多个宿主机之间)。其中macvlan
是基于虚拟物理地址的mac
地址(须要开启网卡的混杂模式promiscuous mode
,且支持vlan)的模式。这里主要说单机模式的最多见的以上三种。node
如下操做环境为Ubuntu 20.04 LTS
,若是采用win
或者mac
的docker desktop
。结果可能没法正常运行~。另外建议你们直接面向 官方文档编程^_^。
回顾如下咱们以前用到的最可能是虚拟机(这里指virtualbox
vmware
),他们有如下几种经常使用网络模式:linux
none
网络none
网络,表明使用容器自身网络,与世隔绝,本身在小黑屋high的。可能用到的场景为是涉及到安全、数据清洗、内部erp之类(我yy的)。参考例子以下:(--rm
表明运行完容器自清理,-ti
表明交互模式,并开启一个终端,docker run更多命令解析)nginx
docker run --name busyboxNoneNet --rm -it --network=none busybox / # ifconfig lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
host
网络直接上代码git
docker run --name 1busyboxHostNet -it --network=host busybox
host
网络会看到宿主机的全部网络,注意是全部。这个名字虽然叫host,主机内网络能看到的,在容器内都能看到且访问到。可是主机向容器内访问不到,容器ping 主机ip能够。
一些特色:github
hostname
,发现和宿主机是同样的【可是注意权限有明确区分】ps -ef
命令或者cat /etc/user
命令,容器内与宿主机就不一样了。能够看出除了 Net和user没有隔离, user ,pid,mount ,ipc都进行了隔离。#宿主机 root@volvo:/home/tb# hostname volvo root@volvo:/home/tb# ps -aux |wc -l 306 root@volvo:/home/tb# root@volvo:/etc# ls |wc -l 223 root@volvo:/etc# cat /etc/hosts 127.0.0.1 localhost 127.0.1.1 volvo # The following lines are desirable for IPv6 capable hosts ::1 ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters
#容器内 / # hostname volvo / # ps -a PID USER TIME COMMAND 1 root 0:00 sh 10 root 0:00 ps -a / # cd etc/ /etc # ls group hostname hosts localtime mtab network passwd resolv.conf shadow /etc # /etc # cat /etc/hosts 127.0.0.1 localhost 127.0.1.1 volvo # The following lines are desirable for IPv6 capable hosts ::1 ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters /etc #
host其余注意事项docker
host
容器和宿主机的端口可能会产生冲突,好比容器内监听了80,实际上宿主机的80端口也被占用了。使用host
模式的容器不会被分配ip地址(容器通讯的 IP 地址即为宿主机的地址)。能够用如下命令见证:编程
docker run --rm -d --network host --name myNginxHostNet nginx root@volvo:/home/tb# docker inspect myNginxHostNet -f {{.NetworkSettings.Networks.bridge~~~~.IPAddress}} <no value>
Tips:为了作实验,防止docker pull的镜像慢,我这贴一个docker register source
^_^,vim /etc/docker/daemon.json
添加以下,记得重启systemctl restart docker
{ "registry-mirrors": [ "https://kfwkfulq.mirror.aliyuncs.com", "https://2lqq34jg.mirror.aliyuncs.com", "https://pee6w651.mirror.aliyuncs.com", "https://registry.docker-cn.com", "http://hub-mirror.c.163.com" ], "dns": ["8.8.8.8","8.8.4.4"] }
host
模式访问:http://192.168.1.9/
宿主机查看:json
root@volvo:/etc# netstat -anp |grep :80 tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 23113/nginx: master tcp 0 0 192.168.1.9:80 192.168.1.32:52389 ESTABLISHED 23141/nginx: worker
bridge
网络docker自己有就存在一个默认的bridge(如最开始咱们看到的),用户也能够自定义建立的self-bridge(经过docker create network xx
)。bridge
模式是单体宿主机中用于容器通讯最经常使用的方式。Docker bridge
` 模式实现基于虚拟机中使用的 NAT 方式以及docker proxy。nat基于linux的即veth pair。简单的说就是docker daemon
下配置一个docker0的
虚拟网桥,一边链接宿主机,一边连着N多的容器。而后宿主机上会建立一对虚拟的网络接口 veth pair
(这个东西能够理解为链接两个net namespace
的桥梁)
若是须要宿主机和容器之间通讯,则veth pair
的一边挂在docker0上,另外一边挂在不一样的container
中。vim
若是容器要链接外网以及外网到达容器内,那么就是咱们通常概念中的的nat,而docker中最多见的就是端口映射(natp),natp能够根据数据包的进出顺序分为snat(source nat)和dnat(destination nat)。当前这里面docker 还操做了好比iptable,route相关的操做,具体又能够拿来讲说了。。仍是举个简单的例子吧先:好比外界须要访问docker内容器,
nginx
的docker
服务.(前提nginx docker已经暴露了给宿主机80,即常见的expose Port 80:80),流程简单理解以下:natp
的方式修改了包的目的地址(修改目的地址为dnat
),数据经过容器返回给外部的过程就须要snat
。brctl show
)、iptable的一些规则(iptables -t nat -vnL
)以及内核层面的数据包转发(cat /proc/sys/net/ipv4/ip_forward
),这里就不具体说了,由于我也没实际操做。能够具体用wireshark
或者tcpdump
去看看~bridge
仍是本身造一个?另外docker bridge中官方文档,特别指出: 若是使用默认的的bridge网络,容器之间只能用ip
,而不能用container Name
(除非你显示指定 --link
,然而这个link
(实际就是在host
中增长一条指向)在后期可能就被废掉),并且全部的容器之间默认均可以直接通讯,这也是一个风险点。另外若是你想把一个容器放到其余网络,若是你使用默认的bridge
,那你只能先停掉,在修改network
,再启用,至关繁琐。因此官方建议使用自建的bridge,本身定义的bridge
就直接两条命令实现容器和网络之间的关闭和链接,另一点使用本身建立的bridge
,默认直接可使用container name
来访问,无需link了。另外使用自定义的bridge还能够分别自定义不一样子网的网桥的子网掩码,mtu
大小,iptable
规则等。
咱们先看一下本机网卡配置
root@volvo:/home/tb# ip a 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 inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: enp2s0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000 link/ether d8:c4:97:0f:4b:c2 brd ff:ff:ff:ff:ff:ff 3: wlp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether e8:2a:44:f1:fc:61 brd ff:ff:ff:ff:ff:ff inet 192.168.1.9/24 brd 192.168.1.255 scope global dynamic noprefixroute wlp3s0 valid_lft 244150sec preferred_lft 244150sec inet6 240e:82:2:cf9:cdf4:d5ce:b3b3:c6fe/64 scope global temporary dynamic valid_lft 258761sec preferred_lft 71149sec inet6 240e:82:2:cf9:f5fb:539d:7ef6:5ee2/64 scope global dynamic mngtmpaddr noprefixroute valid_lft 258761sec preferred_lft 172361sec inet6 fe80::51b0:b9d3:fa60:7dc6/64 scope link noprefixroute valid_lft forever preferred_lft forever 4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether 02:42:d3:86:73:83 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 inet6 fe80::42:d3ff:fe86:7383/64 scope link valid_lft forever preferred_lft forever
这里一共四块网卡,docker0
,lo
没必要说,enp2s0
和wlan
分别表明物理网卡和无线网卡,我这里是用wlan
咱们分别启动两个container
,注意默认为bridge
模式。
docker run --name demo1 --rm -it busybox /bin/sh docker run --name demo2 --rm -it busybox /bin/sh
再次宿主机中执行ip a
发现多了两块。注意编号分别为14
,16
。记住这两个数字
14: vethf42774d@if13: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default link/ether 7e:df:8d:d4:54:a0 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet6 fe80::7cdf:8dff:fed4:54a0/64 scope link valid_lft forever preferred_lft forever 16: veth21a33a9@if15: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default link/ether ca:35:58:9b:0e:77 brd ff:ff:ff:ff:ff:ff link-netnsid 1 inet6 fe80::c835:58ff:fe9b:e77/64 scope link
分别在demo1和demo2容器内执行 ip a
demo2中:
/ # 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 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
demo1中为【eth0@if16】
# 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 15: eth0@if16: <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 eth0 valid_lft forever preferred_lft forever
而后咱们在宿主机上查看一下网桥信息 ,具体的对应关系能够参考上面的【13,15】 【14,16】去查找。好比宿主机中的14
号显示和13
作关联,那么13
就表明某一个容器内的网卡编号,而这个容器内的网卡也会关联到宿主机的14
。(brctl自己也能够建立网桥,绑定网卡,设置网关、子网掩码等,只不过docker把这些动做至关于都封装了)
root@volvo:/home/tb# brctl show bridge name bridge id STP enabled interfaces docker0 8000.0242d3867383 no veth21a33a9 vethf42774d
咱们停掉demo1
以后,再宿主机上查看 ip a,会发现网卡已经少了一个
... 4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:d3:86:73:83 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 inet6 fe80::42:d3ff:fe86:7383/64 scope link valid_lft forever preferred_lft forever 14: vethf42774d@if13: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default link/ether 7e:df:8d:d4:54:a0 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet6 fe80::7cdf:8dff:fed4:54a0/64 scope link valid_lft forever preferred_lft forever root@volvo:/home/tb#
固然你以为这里很乱也没有关系,早已经有大神简单实现了这个配对的寻找办法。这里有个小工具dockerveth
,不用肉眼识别,直接一把梭。
docker
的网络与容器之间能够任意搭配,咱们能够根据业务状况建立本身的bridge
,并且能够配置cidr
,gateway
等,但以上介绍的模式是基础,是小打小闹,本身测试环境拿来玩玩儿还能够,在真正的生产环境,是须要跨主机甚至跨平台的,并且机器数量巨大,经过nat这种方式不能知足GDP的快速增长。。利用overlay
等技术实现跨宿主机、跨平台的的docker
之间的透明通讯才是咱们应该去掌握的。后序会结合swarm和k8s看是如何调度通讯的。