大量的網際網路應用服務包含多個服務元件,這往往需要多個容器之間通過網路通訊進行相互配合。Docker 目前提供了對映容器埠到宿主主機和容器互聯機制來為容器提供網路服務。接下來我們將講述 Docker 的網路功能,包括使用埠對映機制來將容器內應用服務提供給外部網路,以及通過容器互聯絡統讓多個容器之間進行快捷的網路通訊。
埠對映實現訪問容器
從外部訪問容器應用
在啟動容器的時候,如果不指定對應的引數,在容器外部是無法通過網路來訪問容器內的網路應用和服務的。當容器中執行了一些網路應用,要讓外部訪問這些應用時,可以通過 -P 或 -p 引數來指定埠對映。當使用 -P 引數時,Docker 會隨機選擇一個主機可用的埠對映至容器內部開放的網路埠:
$ docker run -d -P training/webapp python app.py
使用 docker ps 命令檢視一下對映結果:
我這裡主機的 32768 埠對映到了容器的 5000 埠。此時訪問主機的 32768 埠就可以訪問容器內 web 應用提供的內容。
-p (小寫)引數則可以指定要對映的主機埠。注意,在一個指定的主機埠上只能繫結一個容器。我們可以通過不同的引數格式對映主機和容器之間的埠:
Ip:hostPort:containerPort
Ip::containerPort
hostPort:containerPort
對映所有介面地址
使用 hostPort:containerPort 格式將本地的 5000 埠對映到容器的 5000 埠,可以執行如下命令:
$ sudo docker run -d -p 5000:5000 training/webapp python app.py
此時預設會繫結本地所有介面上的所有地址(如果主機有多個 IP,那麼每個 IP 的 5000 埠都對映到了容器的 5000 埠)。
多次使用 -p 引數可以繫結多個埠:
$ sudo docker run -d -p 5000:5000 -p 3000:80 training/webapp python app.py
對映到指定地址的指定埠
可以使用 ip:hostPort:containerPort 格式的引數指定對映使用一個特定地址,比如 localhost 地址 127.0.0.1:
$ sudo docker run -d -p 127.0.0.1:5000:5000 training/webapp python app.py
對映到指定地址的任意埠
使用 ip::containerPort 格式的引數可以繫結 localhost 的任意埠到容器的 5000 埠,本地主機會自動分配一個埠:
$ sudo docker run -d -p 127.0.0.1::5000 training/webapp python app.py
另外還可以使用 udp 標記來指定 udp 埠:
$ sudo docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py
檢視對映埠配置
使用 docker port 命令可以檢視當前對映的埠配置,也可以檢視到繫結的地址:
上圖中 mad_einstein 是容器的名字,32768 是容器的 5000 埠對映到主機上的埠。
容器互聯實現容器間通訊
容器的連線(linking)系統是除了埠對映外另一種可以與容器中應用進行互動的方式。它會在源和接收容器之間建立一個隧道,接收容器可以看到源容器指定的資訊。
自定義容器命名
連線系統依據容器的名稱來執行。因此,首先需要自定義一個好記的容器名稱。雖然當建立容器的時候,系統預設會分配一個名字,但自定義命名容器有兩個好處:
1. 自定義的名稱比較好記。
2. 當要連線其他容器的時候,可以作為一個有用的參考點,比如連線 web 容器到 db 容器。
使用 –name 標記可以為容器自定義名稱:
$ sudo docker run -d -P –name web training/webapp python app.py
使用 docker ps 來驗證設定的名稱:
也可以使用 docker inspect 來檢視容器的名稱:
注意,容器的名稱是唯一的。如果已經命名了一個叫 web 的容器,當你要再次使用 web 這個名稱的時候,需要先用 docker rm 來刪除之前建立的同名容器。
在執行 docker run 的時候如果新增 – rm 標記,則容器在終止後會立刻刪除。但 – rm 和 -d 不能同時使用。
容器互聯
使用 –link 引數可以讓容器之間安全的進行互動。
下面先建立一個新的資料庫容器:
$ sudo docker run -d –name db training/postgres
刪除之前建立的web容器:
$ sudo docker rm -f web
然後建立一個新的 web 容器,並將它連線到 db 容器:
$ sudo docker run -d -P –name web –link db:db training/webapp python app.py
此時,db 容器和 web 容器建立互聯關係。
--link 引數的格式為 –link name:alias,其中 name 是要連線的容器的名稱,alias 是這個連線的別名。
Docker 在兩個互聯的容器之間建立了一個安全隧道,而且不用對映它們的埠到宿主主機上。在啟動 db 容器的時候沒有使用 -p 和 -P 標記,從而避免了暴露資料庫埠到外部網路上。
Docker 通過兩種方式為容器公開連線資訊:
1. 環境變數。
2. 更新 /etc/hosts檔案。
使用 env 命令來檢視 web 容器的環境變數:
$ sudo docker run –rm –name web2 –link db:db training/webapp python app.py env
其中 DB_ 開頭的環境變數是供 web 容器連線 db 容器使用的。
除了環境變數,Docker 還新增了 host 資訊到容器的 /etc/hosts 檔案中。下面檢視web容器的 hosts 檔案:
$ sudo docker run -t -I –rm –link db:db training/webapp /bin/bash
上圖中有兩個 host 資訊,第一個是 db 容器的名稱 ip 和主機名。第二個是 web 容器,web 容器用自己的 id 作為預設主機名。我們可以通過 ping 命令測試 web 容器到db容器的連線:
如圖所示,名稱 db 被解析成了 172.17.0.24。