在使用Docker容器時,咱們須要訪問容器的內部網絡,或須要在容器間相互訪問。Docker 容器默認不會開聽任何端口,所以須要將容器與宿主機進行端口映射,使容器可外部訪問。而容器間互相訪問,除了能夠基於端口映射進行訪問外,還能夠經過容器連接(Link)的方式,也能夠經過Docker 網絡(Networking)實現。html
端口映射與外部訪問容器python
1.1 -P
綁定宿主機隨機端口linux
1.2 -p
指定端口、IP地址綁定web
1.3 其它docker
容器連接(Link)數據庫
2.1 容器的命名express
2.2 容器的互聯npm
Docker網絡(Networking)安全
3.1 建立網絡bash
3.2 建立容器並鏈接到網絡
3.3 將已有容器鏈接到Docker網絡
3.4 斷開網絡與網絡刪除
Docker 容器運行後默認不會開啓任何網絡端口,這樣就沒法經過網絡訪問容器。要使容器能夠經過外部網絡訪問Docker 容器的內部網絡,就須要將容器端口與宿主機端口創建映射關係。
容器與宿主機間創建端口映射關係時,能夠在運行容器時使用-P
或-p
參數指定端口映射。二者區別以下:
-P
參數會隨機分配一個49000~49900
之間的端口到容器內部開放的網絡(經過EXPORT
指定的)端口
-p
則能夠具體指定要映射的端口,而且在一個指定端口上只能綁定一個容器
-P
綁定宿主機隨機端口-P
參數會隨機綁定一個49000~49900
之間的端口所運行容器的導出端口。
如,運行一個容器,並使用-P
綁定宿主機端口:
$ sudo docker run -d --name experss-app -P itbilu/express-app 28003e2dcdcd38075d1ad68d4791c77edaca47dc3d468b0333669ba483cd7b3d
在這個示例中,咱們經過itbilu/express-app
鏡像建立並運行了一個名爲express-app
的容器。運行容器時,咱們經過-P
參數進行了端口映射。這時,能夠經過docker ps
命令查看所分配的端口號:
$ sudo docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0781edb13563 itbilu/express-app "npm start" 15 seconds ago Up 14 seconds 0.0.0.0:32771->3000/tcp experss-app
如上所示,宿主機的32771
端口被綁定到了容器的3000
端口。
-p
指定端口、IP地址綁定若是不想使用隨機端口,則可使用-p
參數來指定要綁定的端口號。-p
參數除了能夠指定端口號外,還能夠指定宿主機的IP,這一點在使用過程當中很是有用。
-p
支持如下幾種綁定格式:
// 綁定宿主機IP及端口 ip:hostPort:containerPort // 綁定宿主機IP ip::containerPort // 綁定宿主機端口 hostPort:containerPort
綁定宿主機全部的IP
使用hostPort:containerPort
格式進行宿主機及容器端口映射時,默認會將宿主機的全部IP綁定到容器。如:
$ sudo docker run -d --name experss-app -p 3000:3000 itbilu/express-app
在這個示例中,將宿主機的3000
端口映射到了容器的3000
端口。在這種狀況下,會綁定本地全部接口上的全部IP地址。
映射到指定地址的指定端口
使用ip:hostPort:containerPort
格式能夠將宿主機指定的IP及端口,綁定到容器端口。
如,綁定127.0.0.1
IP到容器:
$ sudo docker run -d --name experss-app -p 127.0.0.1:3000:3000 itbilu/express-app
映射指定地址及隨機端口
ip::containerPort
格式會綁定宿主機的指定IP地址及隨機端口到容器端口。如:
$ sudo docker run -d --name experss-app -p 127.0.0.1::3000 itbilu/express-app
使用docker ps
查看所分配的端口:
$ sudo docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 6289a4714594 itbilu/express-app "npm start" 4 seconds ago Up 4 seconds 127.0.0.1:32768->3000/tcp experss-app
在前面示例中,咱們經過docker ps
查看已建立的容器及容器所綁定的端口。除了docker ps
命令外,還可使用docker port
查看所綁定的端口及IP地址:
$ sudo docker port experss-app 3000/tcp -> 127.0.0.1:32768
容器內部可能會使用多個網絡端口,使用docker port
命令時,能夠指定端口參數,以查看容器指定端口的綁定狀況:
$ sudo docker port experss-app 3000 127.0.0.1:32768
在建立/運行容器時,-p
參數能夠被屢次使用,以綁定多個容器端口:
$ sudo docker run -d --name experss-app -p 3000:3000 -p 5000:80 itbilu/express-app
Docker進行端口綁定時,默認會綁定TCP端口。還可使用udp
標記來綁定udp
端口:
$ sudo docker run -d --name experss-app -p 3000:3000/udp itbilu/express-app
容器的鏈接(link)系統是除了端口映射外,另外一種跟容器中應用交互的方式。該系統會在源容器和接收容器之間建立一個隧道,接收容器能夠看到源容器指定的信息。Docker的連接是一個能夠將具體的容器鏈接到一塊兒來進行通訊的抽像層。
Docker的鏈接系統會依據容器的名稱來進行鏈接,所以,首先須要定義容器的名稱。在不指定容器命令的狀況,系統會隨機分配一個名稱。但相對來講,自定義容器名稱更容易記。
自定義容器名稱,可使用--name
參數:
$ sudo docker run -d --name db training/postgres
命令並運行容器後,能夠經過docker ps
命令來查看相關信息。也可使用docker inspect
命令來查看容器的名稱:
$ sudo docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES db2093b13127 training/postgres "su postgres -c '/..." 4 seconds ago Up 2 seconds 5432/tcp db
$ sudo docker inspect -f "{{ .Name }}" db2093b13127 /db
使用--link
參數可讓容器間安全的進行互聯。
如,咱們能夠像下面這樣建立一個名爲web
的容器,並將它鏈接到db
容器:
$ sudo docker run -d -P --name web --link db:db training/webapp python app.py
這樣就在web
和db
之間創建了互聯關係。
--link
參數格式
--link
參數的格式爲--link name:alias
,其中:name
表示要鏈接的容器的名稱,而alias
表示鏈接後的別名。
經過--link
參靈敏,Docker 會在兩個互聯的容器之間建立了一個安全的隧道,且不用映射它們的端口到宿主主機上。在前面咱們啓動db
容器的時,並無使用-p
和-P
參數,從而避免了暴露數據庫端口到外部網絡上,增長了容器的安全性。
在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 network ls NETWORK ID NAME DRIVER SCOPE 32dfd86b7900 bridge bridge local 18814c612f64 host host local 7914b1c3168c none null local
在Docker歷史上,這三個網絡是Docker執行的一部分。在運行容器時,可使用--network
指定要運行容器的網絡,面這三個網絡均可選。
Docker Networking
容許用戶建立本身的網絡,容器間能夠經過這個網絡互相通信。Docker Networking
容許容器跨越不一樣的宿主機通信,且網絡配置方式更靈活。
Docker Engine 會在引擎安裝時自動建立一個名爲bridge
(橋接)網絡,這個網絡會與docker0
(Docker內部網絡)相對應。
除此以外,用戶還能夠自行建立bridge
或overlay
類型的網絡。bridge
網絡適用於單臺宿主機運行的單Docker引擎環境,而overlay
網絡容許咱們跨多臺宿主機進行通信。
要實現Docker Networking
互聯,首先要使用docker network create
命令建立一個網絡:
$ sudo docker network create my_network 32ddd24fd698665888ffa542215ae79a140b31ab3a10c96422ce2aee67b904a9
如上,咱們建立了一個名爲my_network
的網絡,如今能夠經過docker network inspect
查看這個新建的網絡:
$ sudo docker network inspect my_network [ { "Name": "my_network", "Id": "32ddd24fd698665888ffa542215ae79a140b31ab3a10c96422ce2aee67b904a9", "Created": "2017-04-04T04:05:13.230681143Z", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "172.18.0.0/16", "Gateway": "172.18.0.1" } ] }, "Internal": false, "Attachable": false, "Containers": {}, "Options": {}, "Labels": {} } ]
在不添加額外參數的狀況下,建立的是一個本地橋接網絡。而建立overlay
網絡,須要預先存在一些條件,詳細官方文檔:Create networks
使用docker network ls
命令也能夠看到這個新建的網絡:
$ docker network ls NETWORK ID NAME DRIVER SCOPE 32ddd24fd698 my_network bridge local ae4ab5ad7602 bridge bridge local 18814c612f64 host host local 7914b1c3168c none null local
建立網絡後,能夠在建立容器時經過--network
參數指定容器要使用的網絡:
$ sudo docker run -d --name db --network=my_network training/postgres
使用docker network inspect
查看的網絡狀況:
$ docker network inspect my_network [ { "Name": "my_network", "Id": "32ddd24fd698665888ffa542215ae79a140b31ab3a10c96422ce2aee67b904a9", "Created": "2017-04-04T04:05:13.230681143Z", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "172.18.0.0/16", "Gateway": "172.18.0.1" } ] }, "Internal": false, "Attachable": false, "Containers": { "dccb4267650d8659e65aa3876ec6a427224111a91b4b253bb105af2295ad7a4a": { "Name": "db", "EndpointID": "6b1610e37eafbd044beb33f91f1d5d8e337da1b7376690f05b6fdeb0916edb9f", "MacAddress": "02:42:ac:12:00:02", "IPv4Address": "172.18.0.2/16", "IPv6Address": "" } }, "Options": {}, "Labels": {} } ]
能夠看到my_network
網絡的Containers
參數中,包含了網建立的容器的信息,表中容器已鏈接到咱們所建立的網絡,而該容器的IP地址爲172.18.0.2
。
接下來,建立一個交互式容器,並查看該容器內部的網絡狀況:
$ sudo docker run -t -i --name web --network=my_network training/webapp /bin/bash root@acb03a7adec2:/opt/webapp#
而後使用ping
測試是否能夠鏈接到db
容器:
# ping db PING db (172.18.0.2) 56(84) bytes of data. 64 bytes from db.my_network (172.18.0.2): icmp_seq=1 ttl=64 time=0.136 ms 64 bytes from db.my_network (172.18.0.2): icmp_seq=2 ttl=64 time=0.092 ms ...
因而可知在同一網絡中的容器是能夠互相訪問的。
當須要將已在運行的容器添加到已有的網絡時,可使用docker network connect
命令。
刪除剛建立的web
容器,並使用如下命令從新建立:
$ sudo docker run -d --name web training/webapp python app.py
將這個容器鏈接到已建立的名爲my_network
的網絡:
$ sudo docker network connect my_network web
使用docker network inspect
查看的網絡狀況,Containers
節點內容以下:
... "Containers": { "7258828bc9ab9153f060aa38c24daa63e22478632270172f5a1485e0e9a4797b": { "Name": "web", "EndpointID": "457fbf4ecebaabbe6cce2e95d7b1f47e35450897de3e6a00cde835cd3305eee9", "MacAddress": "02:42:ac:12:00:03", "IPv4Address": "172.18.0.3/16", "IPv6Address": "" }, "dccb4267650d8659e65aa3876ec6a427224111a91b4b253bb105af2295ad7a4a": { "Name": "db", "EndpointID": "6b1610e37eafbd044beb33f91f1d5d8e337da1b7376690f05b6fdeb0916edb9f", "MacAddress": "02:42:ac:12:00:02", "IPv4Address": "172.18.0.2/16", "IPv6Address": "" } } ...
一個容器能夠鏈接入多個網絡,從而構建出很是複雜的網絡模型。
還可使用docker network disconnect
命令將容器與網絡斷開鏈接:
$ sudo docker network disconnect my_network web
這樣就將容器web
與網絡my_network
斷開的了鏈接。
網絡不在須要後,可使用docker network rm
命令將網絡刪除:
$ sudo docker network rm my_network
注意:刪除網絡時,須要已斷開所容器的鏈接,不然會刪除失敗。