關於docker的安裝文檔,請參照上篇文章<docker系列二在宿主機上的安裝和卸載>,本文主要針對docker中容器間的通訊方式以內部通訊進行說明。 [toc]html
自從docker容器出現,容器的網絡通訊一直是衆人關注的焦點,而容器的網絡方案又能夠分爲兩大部分:node
咱們在使用docker run建立 Docker 容器時,可使用--network=選項指定容器的網絡模式,Docker 有如下 4 種網絡模式:linux
當Docker進程啓動時,會在主機上建立一個名爲docker0的虛擬網橋,此主機上啓動的Docker容器會鏈接到這個虛擬網橋上。虛擬網橋的工做方式和物理交換機相似,這樣主機上的全部容器就經過交換機連在了一個二層網絡中。從docker0子網中分配一個 IP 給容器使用,並設置 docker0 的 IP 地址爲容器的默認網關。在主機上建立一對虛擬網卡veth pair設備,Docker 將 veth pair 設備的一端放在新建立的容器中,並命名爲eth0(容器的網卡),另外一端放在主機中,以vethxxx這樣相似的名字命名,並將這個網絡設備加入到 docker0 網橋中。能夠經過brctl show命令查看。安裝brctl命令:nginx
yum install -y bridge-utils [root@linux-node4 ~]# brctl show bridge name bridge id STP enabled interfaces docker0 8000.0242d84b7159 no
bridge模式是 docker 的默認網絡模式,不寫–net參數,就是bridge模式。使用docker run -p時,docker 實際是在iptables作了DNAT規則,實現端口轉發功能。可使用iptables -t nat -vnL查看。bridge模式以下圖所示: web
實驗過程以下:docker
docker run --name docker1 nginx:1.13.12 docker run -d --name docker2 nginx:1.13.12
[root@linux-node4 ~]# [root@linux-node4 ~]# brctl show bridge name bridge id STP enabled interfaces docker0 8000.0242d84b7159 no veth8c72f4a vethf15e034 [root@linux-node4 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 75539117a127 nginx:1.13.12 "nginx -g 'daemon of…" About an hour ago Up About an hour 80/tcp docker2 69f1c16d206c nginx:1.13.12 "nginx -g 'daemon of…" About an hour ago Up About an hour 80/tcp docker1 [root@linux-node4 ~]# docker inspect 75539117a127 |grep 172.17 "Gateway": "172.17.0.1", "IPAddress": "172.17.0.3", "Gateway": "172.17.0.1", "IPAddress": "172.17.0.3",
使用自定義的網橋網絡
docker network create -d bridge my-net4 --subnet=192.168.100.1/24
建立一個自定義網橋-d指定模式爲bridge,也能夠爲overlay,--subnet指定子網範圍; 建立兩個容器,並鏈接到咱們自建的網橋:curl
[root@linux-node4 ~]# docker run -d --name=my_test1 --network my-net4 nginx:1.13.12 ffc47de3992c52730ff2590b4b3903fe737521b9c713170d19b747fa2941c8b1
查看容器的網絡地址,驗證其ip地址是不是咱們自定義的網絡。tcp
[root@linux-node4 ~]# docker inspect ffc47de3992 |grep 192 "Gateway": "192.168.100.1", "IPAddress": "192.168.100.2",
注意同一個網橋內的網絡是相互能夠通訊的,本篇不作過多說明。oop
若是啓動容器的時候使用host模式,那麼這個容器將不會得到一個獨立的Network Namespace,而是和宿主機共用一個 Network Namespace。容器將不會虛擬出本身的網卡,配置本身的 IP 等,而是使用宿主機的 IP 和端口。可是,容器的其餘方面,如文件系統、進程列表等仍是和宿主機隔離的。 Host模式以下圖所示:
驗證步驟以下:
建立一個網絡類型爲host的容器 docker run -d --net=host --name=my_host1 nginx:1.13.12
由於nginx容器自己的端口號是80,因此咱們直接使用本地的接口來訪問宿主機的ip和端口號。
[root@linux-node4 ~]# !curl curl http://127.0.0.1:80 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>
若是使用這種網絡模式的時候注意不要一個容器啓動多個實例,會引發端口衝突不能起來,這種網絡模型是沒法使用nat轉化的。 host模式有利也有弊,主要包括如下缺點:
- 容器沒有隔離、獨立的網絡棧:容器由於與宿主機共享網絡而爭搶資源,而且容易崩潰也可能致使主機崩潰,這在生產環境是不容許發生的;
- 端口資源:docker host上已經使用的端口就不能再使用了 host模式的優勢以下:
- 能夠直接使用宿主機ip與外界通訊,無需額外進行nat轉換,因爲容器與外部通訊,再也不須要使用bridge等方式轉發或者進行數據包的封裝,性能上有很大優點。
這個模式指定新建立的容器和已經存在的一個容器共享一個 Network Namespace,而不是和宿主機共享。新建立的容器不會建立本身的網卡,配置本身的 IP,而是和一個指定的容器共享 IP、端口範圍等。一樣,兩個容器除了網絡方面,其餘的如文件系統、進程列表等仍是隔離的。兩個容器的進程能夠經過 lo 網卡設備通訊。 Container模式示意圖:
咱們仍是經過實驗來驗證這個結論吧,上文咱們已經建立了一個自定義網橋的容器,連接到這個容器裏面便可
[root@linux-node4 ~]# docker run -d --name docker_con3 --net=container:ffc47de3992c busybox sleep 6000 933dd7fce1a67883869a6235c3a4f7835c983e079592087734715d05f6bd755e 進入容器內部驗證網絡是否跟預期一致: [root@linux-node4 ~]# docker exec -it 933dd7fce1a6 sh / # ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1 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 33: eth0@if34: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:c0:a8:64:02 brd ff:ff:ff:ff:ff:ff inet 192.168.100.2/24 brd 192.168.100.255 scope global eth0 valid_lft forever preferred_lft forever / # route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 192.168.100.1 0.0.0.0 UG 0 0 0 eth0 192.168.100.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
使用none模式,Docker 容器擁有本身的 Network Namespace,可是,並不爲Docker 容器進行任何網絡配置。也就是說,這個 Docker 容器沒有網卡、IP、路由等信息。須要咱們本身爲 Docker 容器添加網卡、配置 IP 等。 None模式示意圖:
[root@linux-node4 ~]# docker run -d --net=none --name docker_none2 busybox sleep 6000 247fb9eace8b5dedcb47b7f2015eb06f18d4eb67eb323560dcfaaf7ef1069773 網絡狀況驗證: [root@linux-node4 ~]# docker exec -it 247fb9eace8b /bin/sh / # ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1 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 / # route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface / #