平常開發中,接觸最先的是虛擬機(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看是如何調度通訊的。