昨天的最後,我們檢查容器的 IP 位置,竟然發現和本機的 IP 位置不相同,所以得先從電腦的防火牆說起,這和網際網路的請求如何進入容器習習相關。
電腦的防火牆
相信這個名字大家一定不陌生,尤其從小玩 Windows 桌機長大的小孩,一定常常看到關於防火牆設定的通知跳出來,那這到底是什麼,跟 Docker 又有什麼關係呢?
防火牆最一開始的意思,是古人使用木頭建造房屋時,為了避免火災發生及蔓延,將堅固石塊堆砌在房屋周圍做為屏障。
這種防護結構建築就被稱為防火牆。現代網路也參照這個寓意,指隔離本機網路與外界網路的一道防禦系統,藉由控制過濾限制訊息來保護內部網路資料的安全。
防火牆本身預設阻止所有從網際網路中進來的流量;提到防火牆就是希望透過這個方式更理解 Docker 是如何向網際網路打開大門的。
防火牆的門戶大開
正常情況下,Docker 預設會有一個叫做 bridge 的虛擬網路,我們可以透過下方指令查看:
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
8089a4c2e32a bridge bridge local
....
而就是這個虛擬網路幫助我們橋接了本機的網路介面,讓我們可以透過簡單的 --publish
指令,快速的啟動服務並對應到防火牆該開啟哪個 port。
而我們若是沒有指定虛擬網路的情況下,Docker 都會默認使用這個 bridge 的虛擬網路,以我們從一開始到現在的 nginx 服務為例,搭配下方的圖片:
這和一開始介紹容器生命週期時所繪製的圖很像,就加上防火牆以及虛擬網路而已。
但這也牽扯到剛剛提過的分配 IP 位置,為什麼 nginx 的容器預設不會被分配到和本機相同的 IP 位置呢?
是因為沒有指定網路的話,容器都會以 Docker 的 bridge 虛擬網路為優先並連接上去,所以不同的網路環境當然會顯示不相同的 IP 位置。
我們也可以透過 inspect 的指令來查看 bridge 這個虛擬網路本身的 IP 位置:
$ docker network inspect bridge
[
...
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
...
]
可以觀察到在 Config 裡面的 Gateway 寫著 172.17.0.1,而我們啟動的 nginx 服務則是在 172.17.0.2,若是再開一個 nginx 服務呢?
$ docker container run --detach --publish 8080:80 --name nginx2 nginx # 不換行
b76c49631846d8b2249f7c4c...
$ docker container inspect --format '{{ .NetworkSettings.IPAddress }}' nginx2 # 不換行
172.17.0.3
像剛剛所說的,因為沒有指定虛擬網路的情況下,預設使用 bridge 這個虛擬網路,而 Docker 則替我們在 bridge 這個網路內分配了 IP 位置,而且看起來分配的還是挺有規律的呢。
但即使容器被分配到了不同的 IP 位置,但這又和網際網路能夠進入容器的服務有什麼關係呢?
其實是 Docker 透過了 NAT ( 網路位址轉換 ) 這項技術,讓外部的請求進入 Docker 並找到容器的,而 NAT 這項技術被廣泛地使用在許多公司的內部網路,或是私人企業的內網。
主要原因是 IPv4 位置稀少,而很多企業或網路公司在只擁有少數 IP 位置情況下,但公司內部確有太多電腦要連接網路,故採取共用 IP 的解決方法,就是讓一個 IP 位置給多臺電腦使用。
使用者上網後,拿到一個 IP 位置,而 IP 分享器或無線基地台則將一組專供內部使用的私有 IP,通常是 192.168.0.x,分配給所有內部電腦,內部每部電腦擁有一個 192.168.0.x 的 IP 位置,但無線基地台對外卻只有一個由網路公司賦予的 IP 位置。
通常 NAT 將每一部電腦所用的 IP,對應到共用 IP,且 NAT 負責將進出封包的 Header 進行轉換使得內部電腦可以輕鬆地與外部網路連線溝通。
用上述的例子,我們可以想像 Docker 就是那個分配 IP 的機器,而在 Docker 上運作的容器都是公司內部的電腦,被分配了一個 IP 位置,但主要外面的入口還是要通過 Docker 來處理底層的網路技術。
結語
今天更深入的解釋了關於 Docker 的虛擬網路,明天會介紹關於 Docker Network 的指令,以及可以怎麼使用。
感謝閱讀!