一、實現原理
1、實現原理
Docker使用Linux橋接,在宿主機虛擬一個Docker容器網橋(docker0
),Docker啟動一個容器時會根據Docker網橋的網段分配給容器一個IP地址,稱為Container-IP,
同時Docker網橋是每個容器的預設閘道器。因為在同一宿主機內的容器都接入同一個網橋,這樣容器之間就能夠通過容器的Container-IP直接通訊。
Docker網橋是宿主機虛擬出來的,並不是真實存在的網路裝置,外部網路是無法定址到的,這也意味著外部網路無法通過直接Container-IP訪問到容器。如果容器希望外部訪問能夠
訪問到,可以通過對映容器埠到宿主主機(埠對映),即docker run建立容器時候通過 -p 或 -P 引數來啟用,訪問容器的時候就通過[宿主機IP]:[容器埠]訪問容器。
二、四種網路模式
安裝Docker時,它會自動建立三個網路,bridge
(建立容器預設連線到此網路)、 none
、host
安裝好docker,我們可以通過命令來檢視當前的網路模式
[root@izbp13196 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
a6fb564d8107 bridge bridge local
8f63ceca4d5a host host local
de62f8161011 none null local
我們在使用docker run建立Docker容器時,可以用 --net 選項指定容器的網路模式,Docker可以有以下4種網路模式:
host模式:使用 --net=host 指定。
none模式:使用 --net=none 指定。
bridge模式:使用 --net=bridge 指定,預設設定。
container模式:使用 --net=container:NAME_or_ID 指定。
下面分別介紹一下Docker的各個網路模式。
1、Host模式
如果啟動容器時候使用host模式,那麼這個容器將不會獲得一個獨立的Network Namespace,而是和宿主機共用一個NetworkNamespace。容器將不會虛擬出自己的網路卡,
配置自己的IP等,而是使用宿主機的IP和埠。但是,容器的其他方面,如檔案系統、程式列表等還是和宿主機隔離的。
使用host模式的容器可以直接使用宿主機的IP地址與外界通訊,容器內部的服務埠也可以使用宿主機的埠,host最大的優勢就是網路效能比較好,但是docker host上已經
使用的埠就不能再用了,網路的隔離性不好。
2、Container模式
這個模式指定新建立的容器和已經存在的一個容器共享一個Network Namespace,而不是和宿主機共享。新建立的容器不會建立自己的網路卡,配置自己的IP,而是和一個指定的
容器共享IP、埠範圍等。同樣,兩個容器除了網路方面,其他的如檔案系統、程式列表等還是隔離的。兩個容器的程式可以通過lo網路卡裝置通訊。
3、none模式
使用none模式,Docker容器擁有自己的Network Namespace,但是,並不為Docker容器進行任何網路配置。也就是說,這個Docker容器沒有網路卡、IP、路由等資訊。需要我們
自己為Docker容器新增網路卡、配置IP等。
這種網路模式下容器只有lo迴環網路,沒有其他網路卡。none模式可以在容器建立時通過--network=none來指定。這種型別的網路沒有辦法聯網,封閉的網路能很好的保證容器
的安全性。
4、bridge模式
當Docker程式啟動時,會在主機上建立一個名為docker0
的虛擬網橋,此主機上啟動的Docker容器會連線到這個虛擬網橋上。容器啟動時,Docker會建立一對veth pair
(虛擬網路介面)裝置,veth裝置的特點是成對存在,從一端進入的資料會同時出現在另一端。Docker會將一端掛載到docker0網橋上,另一端放入容器的Network Namespace
內,從而實現容器與主機通訊的目的。
bridge模式是docker的預設網路模式,不寫--net引數,就是bridge模式。使用docker run -p時,docker實際是在iptables做了DNAT規則,實現埠轉發功能。
三、 學容器必須懂bridge網路
前面有說過 Docker啟動的時候會在主機上自動建立一個docker0網橋,實際上是一個Linux網橋,所有容器的啟動如果在docker run的時候如果不指定--network,都會掛載
到docker0網橋上。這樣容器就可以和主機甚至是其他容器之間通訊了。
具體看下圖片
1、新建立容器
如果只是安裝了docker,但並沒有啟動任何docker專案,我們可以看到當前 docker0 上沒有任何其他網路裝置
[root@izbp1319 ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242b79eef68 no
這時我們建立一個容器看看有什麼變化。
#啟動容器
[root@izbp13196 ~]# docker run -d httpd
#檢視容器
[root@izbp13196 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ae4959077e70 httpd "httpd-foreground" 17 minutes ago Up 17 minutes 80/tcp loving_ptolemy
再來檢視下網路裝置
[root@izbp13196wp34obmnd4avdz ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242b79eef68 no vethb37e106
一個新的網路介面 vethb37e106
被掛到了 docker0 上,vethb37e106就是新建立容器的虛擬網路卡。
2、檢視新建容器網路配置
我們進入剛建立的容器內部,檢視網路配置。
# ae4959077e70為該容器id
[root@izbp13196 ~]# docker exec -it ae4959077e70 bash
root@ae4959077e70:/usr/local/apache2#
先安裝ip命令,因為預設是沒有ip命令的,所以我們要先安裝這個命令,才能檢視當前容器網路地址
#先更新
root@ae4959077e70:/usr/local/apache2# apt-get update
#在安裝iproute,如果安裝失敗那就安裝iproute2
root@ae4959077e70:/usr/local/apache2# apt-get install iproute
檢視網路
容器有一個網路卡 eth0@if1004
。大家可能會問了,為什麼不是vethb37e106 呢?
實際上 eth0@if1004 和 vethb37e106 是一對 veth pair。veth pair 是一種成對出現的特殊網路裝置,可以把它們想象成由一根虛擬網線連線起來的一對網路卡,網路卡的一頭
(eth0@if1004)在容器中,另一頭(vethb37e106)掛在網橋 docker0 上,其效果就是將 eth0@if1004 也掛在了 docker0 上。
3、檢視宿主機
[root@izbp13196wp34obmnd4avdz ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:16:3e:14:50:2d brd ff:ff:ff:ff:ff:ff
inet 172.16.255.238/20 brd 172.16.255.255 scope global eth0
valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
link/ether 02:42:b7:9e:ef:68 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 scope global docker0
valid_lft forever preferred_lft forever
1004: vethb37e106@if1003: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP
link/ether d6:b4:d1:b6:ee:f0 brd ff:ff:ff:ff:ff:ff link-netnsid 11
把上面整理成一份圖大致就是下面這樣的
四、容器之間的通訊
1、容器內部能否ping通外部?
# 測試 執行一個tomcat
$ docker run -d --name tomcat01 tomcat
# 檢視主機網路地址
$ ip addr
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
551: vethbfc37e3@if550: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 1a:81:06:13:ec:a1 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::1881:6ff:fe13:eca1/64 scope link
valid_lft forever preferred_lft forever
# 進入容器內部,檢視網路地址
$ docker exec -it 容器id
$ ip addr
# 檢視容器內部網路地址 發現容器啟動的時候會得到一個 eth0@if551 ip地址,docker分配!
550: eth0@if551: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
# 思考? linux能不能ping通容器內部! 可以 容器內部可以ping通外界嗎? 可以!
$ ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.069 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.074 ms
原因
:我們每啟動一個docker容器,docker就會給docker容器分配一個ip,我們只要按照了docker,就會有一個docker0橋接模式,使用的技術是veth-pair技術!
2、容器之間能否ping通
# 啟動tomcat01 檢視ip地址為172.17.0.2
$ docker-tomcat docker exec -it tomcat01 ip addr #獲取tomcat01的ip 172.17.0.2
550: eth0@if551: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
#啟動tomcat02 看能否ping通172.17.0.2
$ docker-tomcat docker exec -it tomcat02 ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.098 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.071 ms
# 可以ping通
思考
雖然所我們通過tomcat02,能夠ping通tomcat1,但這裡不是直接ping通過的,而是通過路由器,也就是docker0,來進行橋接的。
參考
1、《每天5分鐘玩轉 Docker 容器技術》書籍