Docker 網路-埠對映、容器連結、Networking
在使用Docker容器時,我們需要訪問容器的內部網路,或需要在容器間相互訪問。Docker 容器預設不會開放任何埠,因此需要將容器與宿主機進行埠對映,使容器可外部訪問。而容器間互相訪問,除了可以基於埠對映進行訪問外,還可以通過容器連結(Link)的方式,也可以通過Docker 網路(Networking)實現。
1. 埠對映與外部訪問容器
Docker 容器執行後預設不會開啟任何網路埠,這樣就無法通過網路訪問容器。要使容器可以通過外部網路訪問Docker 容器的內部網路,就需要將容器埠與宿主機埠建立對映關係。
容器與宿主機間建立埠對映關係時,可以在執行容器時使用-P
或-p
引數指定埠對映。兩者區別如下:
-P
引數會隨機分配一個49000~49900
之間的埠到容器內部開放的網路(通過EXPORT
指定的)埠-p
則可以具體指定要對映的埠,並且在一個指定埠上只能繫結一個容器
1.1 -P
繫結宿主機隨機埠
-P
引數會隨機繫結一個49000~49900
之間的埠所執行容器的匯出埠。
如,執行一個容器,並使用-P
繫結宿主機埠:
在這個示例中,我們通過itbilu/express-app
映象建立並運行了一個名為express-app
的容器。執行容器時,我們通過-P
引數進行了埠對映。這時,可以通過docker ps
命令檢視所分配的埠號:
如上所示,宿主機的32771
埠被繫結到了容器的3000
埠。
1.2 -p
指定埠、IP地址繫結
如果不想使用隨機埠,則可以使用-p
引數來指定要繫結的埠號。-p
引數除了可以指定埠號外,還可以指定宿主機的IP,這一點在使用過程中非常有用。
-p
支援以下幾種繫結格式:
繫結宿主機所有的IP
使用hostPort:containerPort
格式進行宿主機及容器埠對映時,預設會將宿主機的所有IP繫結到容器。如:
在這個示例中,將宿主機的3000
埠對映到了容器的3000
埠。在這種情況下,會繫結本地所有介面上的所有IP地址。
對映到指定地址的指定埠
使用ip:hostPort:containerPort
格式可以將宿主機指定的IP及埠,繫結到容器埠。
如,繫結127.0.0.1
對映指定地址及隨機埠
ip::containerPort
格式會繫結宿主機的指定IP地址及隨機埠到容器埠。如:
使用docker ps
檢視所分配的埠:
1.3 其它
在前面示例中,我們通過docker ps
檢視已建立的容器及容器所繫結的埠。除了docker ps
命令外,還可以使用docker port
檢視所繫結的埠及IP地址:
容器內部可能會使用多個網路埠,使用docker port
命令時,可以指定埠引數,以檢視容器指定埠的繫結情況:
在建立/執行容器時,-p
引數可以被多次使用,以繫結多個容器埠:
Docker進行埠繫結時,預設會繫結TCP埠。還可以使用udp
標記來繫結udp
埠:
2. 容器連結(Link)
容器的連線(link)系統是除了埠對映外,另一種跟容器中應用互動的方式。該系統會在源容器和接收容器之間建立一個隧道,接收容器可以看到源容器指定的資訊。Docker的連結是一個可以將具體的容器連線到一起來進行通訊的抽像層。
2.1 容器的命名
Docker的連線系統會依據容器的名稱來進行連線,因此,首先需要定義容器的名稱。在不指定容器命令的情況,系統會隨機分配一個名稱。但相對來說,自定義容器名稱更容易記。
自定義容器名稱,可以使用--name
引數:
命令並執行容器後,可以通過docker ps
命令來檢視相關資訊。也可以使用docker inspect
命令來檢視容器的名稱:
2.2 容器的互聯
使用--link
引數可以讓容器間安全的進行互聯。
如,我們可以像下面這樣建立一個名為web
的容器,並將它連線到db
容器:
這樣就在web
和db
之間建立了互聯關係。
--link
引數格式
--link
引數的格式為--link name:alias
,其中:name
表示要連線的容器的名稱,而alias
表示連線後的別名。
通過--link
參靈敏,Docker 會在兩個互聯的容器之間建立了一個安全的隧道,且不用對映它們的埠到宿主主機上。在前面我們啟動db
容器的時,並沒有使用-p
和-P
引數,從而避免了暴露資料庫埠到外部網路上,增加了容器的安全性。
3. Docker網路(Networking)
在Docker 1.9及之後,增加了Docker Networking
及docker network
命令。容器之間的連線通過網路來建立,這被稱為Docker Networking
。
通過埠對映的方式開放容器的內部網路,這種方式並不夠靈活、強大,且會暴露埠到外部網路。容器連結和Dcoker Networking是更好的處理方式,Docker 1.9之前的版本推薦使用容器連結(Link)的方式,在Docker 1.9及之後則更推薦使用Dcoker Networking。相對連結來說,Networking具有以下優點:
- Dcoker Networking可以將容器連線到不同宿主機上的容器
- 通過Dcoker Networking連線的容器,可以在不更新連線的情況下對容器進行停止、啟動或重啟。而連結則需要通過更新配置,重啟對應的容器來更新容器之間的網路
- 使用Dcoker Networking可以不用關心容器是否已執行,也不用關心容器的執行順序,而可以在網路內部獲取容器名的解析和發現
Docker 安裝會,有三個網路會被自動建立。可以通過docker network ls
命令檢視:
在Docker歷史上,這三個網路是Docker執行的一部分。在執行容器時,可以使用--network
指定要執行容器的網路,面這三個網路都可選。
3.1 建立網路
Docker Networking
允許使用者建立自己的網路,容器間可以通過這個網路互相通訊。Docker Networking
允許容器跨越不同的宿主機通訊,且網路配置方式更靈活。
Docker Engine 會在引擎安裝時自動建立一個名為bridge
(橋接)網路,這個網路會與docker0
(Docker內部網路)相對應。
除此之外,使用者還可以自行建立bridge
或overlay
型別的網路。bridge
網路適用於單臺宿主機執行的單Docker引擎環境,而overlay
網路允許我們跨多臺宿主機進行通訊。
要實現Docker Networking
互聯,首先要使用docker network create
命令建立一個網路:
如上,我們建立了一個名為my_network
的網路,現在可以通過docker network inspect
檢視這個新建的網路:
在不新增額外引數的情況下,建立的是一個本地橋接網路。而建立overlay
網路,需要預先存在一些條件,詳細官方文件:Create networks
使用docker network ls
命令也可以看到這個新建的網路:
3.2 建立容器並連線到網路
建立網路後,可以在建立容器時通過--network
引數指定容器要使用的網路:
使用docker network inspect
檢視的網路情況:
可以看到my_network
網路的Containers
引數中,包含了網建立的容器的資訊,表中容器已連線到我們所建立的網路,而該容器的IP地址為172.18.0.2
。
接下來,建立一個互動式容器,並檢視該容器內部的網路情況:
然後使用ping
測試是否可以連線到db
容器:
由此可見在同一網路中的容器是可以互相訪問的。
3.3 將已有容器連線到Docker網路
當需要將已在執行的容器新增到已有的網路時,可以使用docker network connect
命令。
刪除剛建立的web
容器,並使用以下命令重新建立:
將這個容器連線到已建立的名為my_network
的網路:
使用docker network inspect
檢視的網路情況,Containers
節點內容如下:
一個容器可以連線入多個網路,從而構建出非常複雜的網路模型。
3.4 斷開網路與網路刪除
還可以使用docker network disconnect
命令將容器與網路斷開連線:
這樣就將容器web
與網路my_network
斷開的了連線。
網路不在需要後,可以使用docker network rm
命令將網路刪除:
注意:刪除網路時,需要已斷開所容器的連線,否則會刪除失敗。