?
This document uses PHP Chinese website manual Release
1:概況介紹
2:集裝箱
3:服務(wù)
4:成群
5:堆疊
6:部署應(yīng)用程序
安裝Docker版本1.13或更高版本...
閱讀第1部分中的方向。
給您的環(huán)境一個(gè)快速測(cè)試運(yùn)行,以確保您已經(jīng)設(shè)置好了:
碼頭經(jīng)營(yíng)哈羅-世界
現(xiàn)在是開(kāi)始以Docker方式構(gòu)建應(yīng)用程序的時(shí)候了。我們將從這種應(yīng)用程序的層次結(jié)構(gòu)的底部開(kāi)始,該應(yīng)用程序是一個(gè)容器,我們將在此頁(yè)面上進(jìn)行介紹。在這個(gè)層次上面是一個(gè)服務(wù),它定義了容器在生產(chǎn)中的行為方式,在第3部分中進(jìn)行了討論。最后,在頂層是堆棧,定義了第5部分中介紹的所有服務(wù)的交互。
堆疊
服務(wù)
集裝箱你在這里
在過(guò)去,如果您要開(kāi)始編寫(xiě)Python應(yīng)用程序,您的首要任務(wù)就是將Python運(yùn)行時(shí)安裝到您的計(jì)算機(jī)上。但是,這就造成了這樣一種情況:為了使應(yīng)用程序按預(yù)期運(yùn)行,計(jì)算機(jī)上的環(huán)境必須是這樣的;運(yùn)行應(yīng)用程序的服務(wù)器也是如此。
使用Docker,您只需獲取一個(gè)可移植的Python運(yùn)行時(shí)作為映像,無(wú)需安裝。然后,您的構(gòu)建可以將基本Python映像與應(yīng)用程序代碼放在一起,確保應(yīng)用程序、其依賴項(xiàng)和運(yùn)行時(shí)都能一起運(yùn)行。
這些便攜式圖像是由稱(chēng)為a的東西定義的Dockerfile
。
Dockerfile
Dockerfile
將定義容器內(nèi)環(huán)境中發(fā)生的事情。在這個(gè)環(huán)境中,對(duì)網(wǎng)絡(luò)接口和磁盤(pán)驅(qū)動(dòng)器等資源的訪問(wèn)是虛擬化的,這與系統(tǒng)的其他部分是隔離的,因此您必須將端口映射到外部世界,并具體說(shuō)明要將哪些文件“復(fù)制”到該環(huán)境。但是,在這樣做之后,您可以預(yù)期您的應(yīng)用程序的構(gòu)建是在Dockerfile
無(wú)論在哪里運(yùn)行都會(huì)表現(xiàn)得完全一樣。
Dockerfile
創(chuàng)建一個(gè)空目錄。將目錄(cd
)更改為新目錄,創(chuàng)建一個(gè)名為的文件Dockerfile
,將以下內(nèi)容復(fù)制并粘貼到該文件中并保存。注意解釋新Dockerfile中每條語(yǔ)句的注釋。
# Use an official Python runtime as a parent image FROM python:2.7-slim # Set the working directory to /app WORKDIR /app # Copy the current directory contents into the container at /app ADD . /app # Install any needed packages specified in requirements.txt RUN pip install -r requirements.txt # Make port 80 available to the world outside this container EXPOSE 80# Define environment variable ENV NAME World # Run app.py when the container launches CMD ["python", "app.py"]
這Dockerfile
指我們還沒(méi)有創(chuàng)建的幾個(gè)文件,即app.py
和requirements.txt
讓我們創(chuàng)造下一個(gè)。
再創(chuàng)建兩個(gè)文件,requirements.txt
和app.py
,并將它們放在同一個(gè)文件夾中,Dockerfile
這就完成了我們的應(yīng)用程序,正如您所看到的,這個(gè)應(yīng)用程序非常簡(jiǎn)單。當(dāng)以上Dockerfile
被塑造成一幅圖像,app.py
和requirements.txt
會(huì)因?yàn)檫@個(gè)而出現(xiàn)Dockerfile
氏ADD
命令的輸出。app.py
可以通過(guò)HTTP訪問(wèn),這要感謝EXPOSE
命令。
requirements.txt
Flask Redis
app.py
from flask import Flaskfrom redis import Redis, RedisErrorimport osimport socket # Connect to Redis redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)app = Flask(__name__)@app.route("/")def hello(): try: visits = redis.incr("counter") except RedisError: visits = "<i>cannot connect to Redis, counter disabled</i>" html = "<h3>Hello {name}!</h3>" \ "<b>Hostname:</b> {hostname}<br/>" \ "<b>Visits:</b> {visits}" return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits)if __name__ == "__main__": app.run(host='0.0.0.0', port=80)
現(xiàn)在我們看到了pip install -r requirements.txt
安裝用于Python的Flask和Redis庫(kù),應(yīng)用程序打印環(huán)境變量NAME
,以及調(diào)用的輸出socket.gethostname()
最后,由于Redis沒(méi)有運(yùn)行%28,我們只安裝了Python庫(kù),而沒(méi)有安裝Redis本身的%29,因此我們應(yīng)該期望在這里使用它的嘗試會(huì)失敗并產(chǎn)生錯(cuò)誤消息。
注:在容器中檢索容器ID時(shí)訪問(wèn)主機(jī)的名稱(chēng),這就像正在運(yùn)行的可執(zhí)行文件的進(jìn)程ID一樣。
而已!您requirements.txt
的系統(tǒng)中不需要Python或其他任何東西,也不會(huì)在您的系統(tǒng)上安裝或運(yùn)行此映像??雌饋?lái)你并沒(méi)有真正用Python和Flask建立一個(gè)環(huán)境,但是你已經(jīng)擁有了。
我們已經(jīng)準(zhǔn)備好構(gòu)建這個(gè)應(yīng)用程序了。確保您仍然處于新目錄的頂層。這是什么ls
應(yīng)顯示:
$ ls Dockerfile app.py requirements.txt
現(xiàn)在運(yùn)行Build命令。這將創(chuàng)建一個(gè)Docker映像,我們將使用它進(jìn)行標(biāo)記-t
所以它有個(gè)友好的名字。
docker build -t friendlyhello .
你的形象在哪里?它在您機(jī)器的本地Docker映像注冊(cè)表中:
$ docker images REPOSITORY TAG IMAGE ID friendlyhello latest 326387cea398
運(yùn)行應(yīng)用程序,使用以下方法將機(jī)器的端口4000映射到容器的已發(fā)布端口80-p
*
docker run -p 4000:80 friendlyhello
您應(yīng)該會(huì)看到Python正在為您的應(yīng)用提供服務(wù)的通知http://0.0.0.0:80
。但是該消息來(lái)自容器內(nèi)部,它不知道你將該容器的端口80映射到4000,從而制作正確的URL http://localhost:4000
。
轉(zhuǎn)到Web瀏覽器中的URL,查看網(wǎng)頁(yè)上的顯示內(nèi)容,包括“HelloWorld”文本、容器ID和Redis錯(cuò)誤消息。
您還可以使用curl
命令在shell中查看相同的內(nèi)容。
$ curl http://localhost:4000<h3>Hello World!</h3><b>Hostname:</b> 8fc990912a14<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>
注*該端口重新映射為
4000:80
是為了證明你EXPOSE
在Dockerfile
,還有你publish
使用docker run -p
在后面的步驟中,我們將只將主機(jī)上的端口80映射到容器中的端口80,然后使用http://localhost
...
命中CTRL+C
在你的終點(diǎn)站辭職。
現(xiàn)在讓我們?cè)诤笈_(tái)以分離模式運(yùn)行該應(yīng)用程序:
docker run -d -p 4000:80 friendlyhello
你得到你的應(yīng)用程序的長(zhǎng)容器ID,然后被踢回你的終端。您的容器正在后臺(tái)運(yùn)行。您還可以看到縮寫(xiě)的容器IDdocker container ls
%28并且在運(yùn)行命令%29時(shí)兩者都可以互換工作:
$ docker container ls CONTAINER ID IMAGE COMMAND CREATED 1fa4ab2cf395 friendlyhello "python app.py" 28 seconds ago
你會(huì)看到的CONTAINER ID
匹配正在進(jìn)行的http://localhost:4000
...
現(xiàn)在用docker stop
若要結(jié)束該進(jìn)程,請(qǐng)使用CONTAINER ID
,就像這樣:
docker stop 1fa4ab2cf395
為了演示我們剛剛創(chuàng)建的圖像的可移植性,讓我們上傳構(gòu)建的映像并在其他地方運(yùn)行它。畢竟,當(dāng)您想要將容器部署到生產(chǎn)中時(shí),您將需要學(xué)習(xí)如何推送到注冊(cè)表。
注冊(cè)表是存儲(chǔ)庫(kù)的集合,存儲(chǔ)庫(kù)是圖像的集合--有點(diǎn)像GitHub存儲(chǔ)庫(kù),只是代碼已經(jīng)構(gòu)建。注冊(cè)中心上的帳戶可以創(chuàng)建許多存儲(chǔ)庫(kù)。大docker
默認(rèn)情況下,CLI使用Docker的公共注冊(cè)表。
注:我們?cè)谶@里使用Docker的公共注冊(cè)表,僅僅是因?yàn)樗敲赓M(fèi)的和預(yù)先配置的,但是有許多公共注冊(cè)表可供選擇,您甚至可以使用碼頭受信任登記處...
如果您沒(méi)有碼頭帳戶,請(qǐng)?jiān)贑loud.docker.com請(qǐng)記下你的用戶名。
登錄到本地計(jì)算機(jī)上的Docker公共注冊(cè)表。
docker login
將本地映像與注冊(cè)表上的存儲(chǔ)庫(kù)關(guān)聯(lián)的符號(hào)是username/repository:tag
標(biāo)記是可選的,但建議使用它,因?yàn)樗亲?cè)表用于為Docker圖像提供一個(gè)版本的機(jī)制。為上下文提供存儲(chǔ)庫(kù)和標(biāo)記有意義的名稱(chēng),如get-started:part1
。這將把圖像放在get-started
存儲(chǔ)庫(kù)并將其標(biāo)記為part1
...
現(xiàn)在,把它放在一起標(biāo)記圖像。跑docker tag image
使用您的用戶名、存儲(chǔ)庫(kù)和標(biāo)簽名,以便圖像將上載到您想要的目的地。該命令的語(yǔ)法是:
docker tag image username/repository:tag
例如:
docker tag friendlyhello john/get-started:part1
跑碼頭形象才能看到你的新標(biāo)記圖像。%28你也可以使用docker image ls
.%29
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE friendlyhello latest d9e555c53008 3 minutes ago 195MB john/get-started part1 d9e555c53008 3 minutes ago 195MB python 2.7-slim 1c7128a655f6 5 days ago 183MB...
將標(biāo)記的圖像上載到存儲(chǔ)庫(kù):
docker push username/repository:tag
一旦完成,這個(gè)上傳的結(jié)果是公開(kāi)的。如果你登錄到碼頭樞紐,您將看到新的圖像,在那里,它的拉命令。
從現(xiàn)在開(kāi)始,你可以用docker run
并使用以下命令在任何機(jī)器上運(yùn)行您的應(yīng)用程序:
docker run -p 4000:80 username/repository:tag
如果映像在機(jī)器上本地不可用,Docker將從存儲(chǔ)庫(kù)中提取它。
docker image rm <image id>
$ docker run -p 4000:80 john/get-started:part1 Unable to find image 'john/get-started:part1' locally part1: Pulling from orangesnap/get-started 10a267c67f42: Already exists f68a39a6a5e4: Already exists 9beaffc0cf19: Already exists 3c1fe835fb6b: Already exists 4c9f1fa8fcb8: Already exists ee7d8f576a14: Already exists fbccdcced46e: Already exists Digest: sha256:0601c866aab2adcc6498200efd0f754037e909e5fd42069adeff72d1e2439068 Status: Downloaded newer image for john/get-started:part1 * Running on http://0.0.0.0:80/ (Press CTRL+C to quit)
注*如果不指定
:tag
這些命令的一部分,標(biāo)記為:latest
將在構(gòu)建和運(yùn)行映像時(shí)假設(shè)。Docker將使用沒(méi)有指定%28標(biāo)記而運(yùn)行的映像的最后一個(gè)版本,而不一定是最近的映像%29。
不管在哪里docker run
執(zhí)行時(shí),它將提取您的圖像以及Python和requirements.txt
運(yùn)行你的代碼。所有這些都是在一個(gè)整潔的小包中一起運(yùn)行的,主機(jī)只需要安裝Docker就可以運(yùn)行它了。
這一頁(yè)就這么多了。在下一節(jié)中,我們將學(xué)習(xí)如何通過(guò)在服務(wù)...
繼續(xù)第3部分
這是本頁(yè)所涵蓋內(nèi)容的終端記錄*
下面列出了這個(gè)頁(yè)面中的基本Docker命令,以及一些相關(guān)的命令,如果您想在繼續(xù)之前進(jìn)行一番探索的話。
docker build -t friendlyname . # Create image using this directory's Dockerfile docker run -p 4000:80 friendlyname # Run "friendlyname" mapping port 4000 to 80docker run -d -p 4000:80 friendlyname # Same thing, but in detached mode docker container ls # List all running containers docker container ls -a # List all containers, even those not running docker container stop <hash> # Gracefully stop the specified container docker container kill <hash> # Force shutdown of the specified container docker container rm <hash> # Remove specified container from this machine docker container rm $(docker container ls -a -q) # Remove all containers docker image ls -a # List all images on this machine docker image rm <image id> # Remove specified image from this machine docker image rm $(docker image ls -a -q) # Remove all images from this machine docker login # Log in this CLI session using your Docker credentials docker tag <image> username/repository:tag # Tag <image> for upload to registry docker push username/repository:tag # Upload tagged image to registry docker run username/repository:tag # Run image from a registry