天天看點

Docker網絡原則入門:EXPOSE,-p,-P,-link

本文講的是<b>Docker網絡原則入門:EXPOSE,-p,-P,-link</b>,【編者的話】建構多容器應用程式,需要定義網絡參數來設定容器間的通信,可以通過EXPOSE或者-expose暴露端口、使用-p釋出特定端口,還可以用-link等等來實作,這些方法可能會得到一樣的效果,但是這些方法之間是否有不同,應該選擇什麼樣的方法,将是本文讨論的重點内容。

Docker網絡原則入門:EXPOSE,-p,-P,-link

如果你已經建構了一些多容器的應用程式,那麼肯定需要定義一些網絡規則來設定容器間的通信。有多種方式可以實作:可以通過<code>--expose</code>參數在運作時暴露端口,或者在Dockerfile裡使用<code>EXPOSE</code>指令。還可以在Docker run的時候通過<code>-p</code>或者<code>-P</code>參數來釋出端口。或者通過<code>--link</code>連結容器。雖然這些方式幾乎都能達到一樣的結果,但是它們還是有細微差別。那麼到底應該使用哪一種呢?

使用-p或者-P來建立特定端口綁定規則最為可靠,EXPOSE可以看做是容器文檔化的方式,謹慎使用--link的方式。

在比較這些不同方式之前,我們先分别了解細節。

有兩種方式可以用來暴露端口:要麼用<code>EXPOSE</code>指令在Dockerfile裡定義,要麼在docker run時指定<code>--expose=1234</code>。這兩種方式作用相同,但是,<code>--expose</code>可以接受端口範圍作為參數,比如 <code>--expose=2000-3000</code>。但是,<code>EXPOSE</code>和<code>--expose</code>都不依賴于主控端器。預設狀态下,這些規則并不會使這些端口可以通過主控端來通路。

基于<code>EXPOSE</code>指令的上述限制,Dockerfile的作者一般在包含<code>EXPOSE</code>規則時都隻将其作為哪個端口提供哪個服務的提示。使用時,還要依賴于容器的操作人員進一步指定網絡規則。和<code>-P</code>參數聯合使用的情況,下文會進一步闡述。不過通過<code>EXPOSE</code>指令文檔化端口的方式十分有用。

本質上說,<code>EXPOSE</code>或者<code>--expose</code>隻是為其他指令提供所需資訊的中繼資料,或者隻是告訴容器操作人員有哪些已知選擇。

實際上,在運作時暴露端口和通過Dockerfile的指令暴露端口,這兩者沒什麼差別。在這兩種方式啟動的容器裡,通過<code>docker inspect $container_id | $container_name</code>檢視到的網絡配置是一樣的:

可以看到端口被标示成已暴露,但是沒有定義任何映射。注意這一點,因為我們檢視的是釋出端口。

ProTip:使用運作時标志<code>--expose</code>是附加的,是以會在Dockerfile的<code>EXPOSE</code>指令定義的端口之外暴露添加的端口。

可以使用<code>-p</code>參數顯式将一個或者一組端口從容器裡綁定到主控端上,而不僅僅是提供一個端口。注意這裡是小寫的p,不是大寫。因為該配置依賴于主控端器,是以Dockerfile裡沒有對應的指令,這是運作時才可用的配置。<code>-p</code>參數有幾種不同的格式:

實際中,可以忽略ip或者hostPort,但是必須要指定需要暴露的containerPort。另外,所有這些釋出的規則都預設為tcp。如果需要udp,需要在最後加以指定,比如<code>-p 1234:1234/udp</code>。如果隻是用指令<code>docker run -p 8080:3000 my-image</code>運作一個簡單的應用程式,那麼容器裡運作在3000端口的服務在主控端的8080端口也就可用了。端口不需要一樣,但是在多個容器都暴露端口時,必須注意避免端口沖突。

避免沖突的最佳方法是讓Docker自己配置設定hostPort。在上述例子裡,可以選擇<code>docker run -p 3000 my_image</code>來運作容器,而不是顯式指定主控端端口。這時,Docker會幫助選擇一個主控端端口。運作指令<code>docker port $container_id | $container_name</code>可以檢視Docker選出的端口号。除了端口号,該指令隻能顯示容器運作時端口綁定資訊。還可以通過在容器上運作<code>docker inspect</code>檢視詳細的網絡資訊,在定義了端口映射時,這樣的資訊就很有用。該資訊在Config、HostConfig和NetworkSettings部分。我們檢視這些資訊來對比不同方式搭建的容器間的網絡差別。

ProTip:可以用<code>-p</code>參數定義任意數量的端口映射。

為了更好得了解兩者之間的差別,我們使用不同的端口設定來運作容器。

運作一個很簡單的應用程式,會在curl它的時候列印'hello world'。稱這個鏡像為no-exposed-ports:

實驗時注意使用的是Docker主機,而不是<code>boot2docker</code>。如果使用的是<code>boot2docker</code>,運作本文示例指令前先運作<code>boot2docker ssh</code>。

注意,我們使用<code>-d</code>參數運作該容器,是以容器一直在背景運作。(端口映射規則隻适用于運作着的容器):

這兒沒有太多的資訊,隻是回顯了容器的ID,提示服務已經成功啟動。和預期結果一樣,運作<code>docker port no-exposed-ports</code>和<code>docker inspect no-exposed-ports</code>時沒顯示什麼資訊,因為我們既沒有定義端口映射規則也沒有釋出任何端口。

是以,如果我們釋出一個端口會發生什麼呢,<code>-p</code>參數和<code>EXPOSE</code>到底有什麼差別呢?

還是使用上文的<code>no-exposed-ports</code>鏡像,在運作時添加<code>-p</code>參數,但是不添加任何expose規則。在<code>config.ExposedPorts</code>裡重新檢視--expose參數或者EXPOSE指令的結果。

太棒了!我們可以看到可用端口。注意預設這是tcp。我們到網絡設定裡看看還有什麼資訊:

注意”Config“部分的暴露端口字段。這和我們使用<code>EXPOSE</code>或者<code>--expose</code>暴露的端口是一緻的。Docker會隐式暴露已經釋出的端口。已暴露端口和已釋出端口的差別在于已釋出端口在主控端上可用,而且我們可以在“HostConfig”和“NetworkSettings”兩個部分都能看到已釋出端口的資訊。

所有釋出(<code>-p</code>或者<code>-P</code>)的端口都暴露了,但是并不是所有暴露(<code>EXPOSE</code>或<code>--expose</code>)的端口都會釋出。

因為<code>EXPOSE</code>通常隻是作為記錄機制,也就是告訴使用者哪些端口會提供服務,Docker可以很容易地把Dockerfile裡的<code>EXPOSE</code>指令轉換成特定的端口綁定規則。隻需要在運作時加上<code>-P</code>參數,Docker會自動為使用者建立端口映射規則,并且幫助避免端口映射的沖突。

添加如下行到上文使用的Web應用Dockerfile裡:

建構鏡像,命名為exposed-ports。

再次用<code>-P</code>參數運作,但是不傳入任何特定的<code>-p</code>規則。可以看到Docker會将<code>EXPOSE</code>指令相關的每個端口映射到主控端的端口上:

很友善,不是麼?

你可能在多容器應用程式裡使用過運作時參數 <code>--link name:alias</code>來設定容器間關系。雖然<code>--link</code>非常易于使用,幾乎能提供和端口映射規則和環境變量相同的功能。但是最好将<code>--link</code>當做服務發現的機制,而不是網絡流量的門戶。

<code>--link</code>參數唯一多做的事情是會使用源容器的主機名和容器ID來更新建立目标容器(使用<code>--link</code>參數建立的容器)的/etc/hosts檔案。

雖然<code>--link</code>對于需要隔離域的小型項目非常有用,它的功能更像服務發現的工具。如果項目中使用了編排服務,比如Kubernetes或者Fleet,很可能就會使用别的服務發現工具來管理關系。這些編排服務可能會不管理Docker的連結,而是管理服務發現工具裡包含的所有服務,在Panamax項目裡使用的很多遠端部署擴充卡正是做這個的。

哪一種網絡選擇更為适合,這取決于誰(或者哪個容器)使用Docker運作的服務。需要注意的是一旦鏡像釋出到Docker Hub之後,你無法知道其他人如何使用該鏡像,是以要盡可能讓鏡像更加靈活。如果你隻是從Docker Hub裡取得鏡像,使用<code>-P</code>參數運作容器是最友善迅速的方式,來基于作者的建議建立端口映射規則。記住每一個釋出的端口都是暴露端口,但是反過來是不對的。

Docker網絡原則入門:EXPOSE,-p,-P,-link

===========================

譯者介紹

崔婧雯,現就職于IBM,進階軟體工程師,負責IBM WebSphere業務流程管理軟體的系統測試工作。曾就職于VMware從事桌面虛拟化産品的品質保證工作。對虛拟化,中間件技術,業務流程管理有濃厚的興趣。

原文釋出時間為:2015-06-22

本文作者:崔婧雯

本文來自雲栖社群合作夥伴DockerOne,了解相關資訊可以關注DockerOne。

原文标題:Docker網絡原則入門:EXPOSE,-p,-P,-link

繼續閱讀