原文地址:
https://docs.docker.com/get-started/part2/#recap-and-cheat-sheet-optional
預(yù)計(jì)閱讀時(shí)間: 14分鐘
先決條件
閱讀第1部分中的方向曹步。
-
為您的環(huán)境提供快速測試運(yùn)行抬闷,以確保您完成所有設(shè)置:
docker run hello-world
介紹
現(xiàn)在是時(shí)候開始使用Docker方式構(gòu)建應(yīng)用程序了。我們從這樣一個(gè)應(yīng)用程序?qū)哟谓Y(jié)構(gòu)的底部開始针饥,這是一個(gè)容器,我們將在此頁面上介紹它需频。高于此級別的是一項(xiàng)服務(wù)丁眼,它定義了容器在生產(chǎn)中的行為方式,如第3部分所述昭殉。最后苞七,在頂層是堆棧,定義了第5部分中介紹的所有服務(wù)的交互 挪丢。
- 堆
- 服務(wù)
- 容器(你在這里)
您的新開發(fā)環(huán)境
在過去蹂风,如果您要開始編寫Python應(yīng)用程序,那么您的第一個(gè)業(yè)務(wù)是在您的計(jì)算機(jī)上安裝Python運(yùn)行時(shí)乾蓬。但是惠啄,這會(huì)導(dǎo)致您的計(jì)算機(jī)上的環(huán)境需要非常適合您的應(yīng)用程序按預(yù)期運(yùn)行,并且還需要與您的生產(chǎn)環(huán)境相匹配。
使用Docker撵渡,您可以將可移植的Python運(yùn)行時(shí)作為映像獲取融柬,無需安裝。然后趋距,您的構(gòu)建可以在應(yīng)用程序代碼旁邊包含基本Python映像粒氧,確保您的應(yīng)用程序,其依賴項(xiàng)和運(yùn)行時(shí)都一起運(yùn)行节腐。
這些可移植映像是由Dockerfile
來定義的外盯。
使用 Dockerfile 定義容器
Dockerfile
定義容器內(nèi)環(huán)境中發(fā)生的事情。對網(wǎng)絡(luò)接口和磁盤驅(qū)動(dòng)器等資源的訪問在此環(huán)境中進(jìn)行虛擬化铜跑,該環(huán)境與系統(tǒng)的其他部分隔離门怪,因此您需要將端口映射到外部世界,并具體說明要“復(fù)制”到哪些文件那個(gè)環(huán)境锅纺。但是掷空,在執(zhí)行此操作之后,您可以預(yù)期Dockerfile
在此處定義的應(yīng)用程序的構(gòu)建 在其運(yùn)行的任何位置都會(huì)完全相同囤锉。
Dockerfile
創(chuàng)建一個(gè)空目錄坦弟。(cd
)到新目錄,創(chuàng)建一個(gè)名為Dockerfile
的文件官地,將以下內(nèi)容復(fù)制并粘貼到該文件中酿傍,然后保存。注意新Dockerfile中每個(gè)語句的注釋驱入。
# 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 --trusted-host pypi.python.org -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
是指我們尚未創(chuàng)建的幾個(gè)文件赤炒,即 app.py
和requirements.txt
。讓我們創(chuàng)建下一個(gè)亏较。
應(yīng)用程序本身
再創(chuàng)建兩個(gè)文件莺褒,requirements.txt
然后app.py
將它們放在Dockerfile
的同一個(gè)文件夾中。這完成了我們的應(yīng)用程序雪情,您可以看到它非常簡單遵岩。當(dāng)上述Dockerfile
被build進(jìn)映像,app.py
和requirements.txt
的存在因?yàn)?code>Dockerfile的ADD
命令巡通,通過HTTP訪問app.py
得益于EXPOSE
命令尘执。
requirements.txt
Flask
Redis
app.py
from flask import Flask
from redis import Redis, RedisError
import os
import 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庫,應(yīng)用程序打印環(huán)境變量NAME
宴凉,以及調(diào)用的輸出socket.gethostname()
誊锭。最后,因?yàn)镽edis沒有運(yùn)行(因?yàn)槲覀冎话惭b了Python庫弥锄,而不是Redis本身)炉旷,我們在這里會(huì)看到它嘗試使用失敗并產(chǎn)生錯(cuò)誤消息签孔。
注意:在容器內(nèi)部訪問容器ID時(shí),訪問主機(jī)名稱窘行,這類似于正在運(yùn)行的可執(zhí)行文件的進(jìn)程ID。
就是這樣图仓!您不需要Python或requirements.txt
系統(tǒng)中的任何內(nèi)容罐盔,也不需要構(gòu)建或運(yùn)行此映像將它們安裝在您的系統(tǒng)上【却蓿看起來你并沒有真正建立一個(gè)Python和Flask的環(huán)境惶看,但你有。
構(gòu)建應(yīng)用程序
我們準(zhǔn)備構(gòu)建應(yīng)用程序六孵。確保您仍處于新目錄的頂層纬黎。這是ls
應(yīng)該顯示的內(nèi)容:
$ ls
Dockerfile app.py requirements.txt
現(xiàn)在運(yùn)行build命令。這會(huì)創(chuàng)建一個(gè)Docker鏡像劫窒,我們將使用-t
它來標(biāo)記本今,因此它具有友好的名稱。
docker build -t friendlyhello .
你的建立的映像在哪里主巍?它位于您機(jī)器的本地Docker鏡像注冊表中:
$ docker image ls
REPOSITORY TAG IMAGE ID
friendlyhello latest 326387cea398
Linux用戶的故障排除
代理服務(wù)器設(shè)置
代理服務(wù)器可以在啟動(dòng)并運(yùn)行后阻止與Web應(yīng)用程序的連接冠息。如果您位于代理服務(wù)器后面,請使用以下
ENV
命令將以下行添加到Dockerfile中孕索,以指定代理服務(wù)器的主機(jī)和端口:# Set proxy server, replace host:port with values for your servers ENV http_proxy host:port ENV https_proxy host:port
DNS設(shè)置
DNS配置錯(cuò)誤可能會(huì)產(chǎn)生問題
pip
逛艰。您需要設(shè)置自己的DNS服務(wù)器地址才能pip
正常工作。您可能想要更改Docker守護(hù)程序的DNS設(shè)置搞旭。您可以/etc/docker/daemon.json
使用dns
密鑰編輯(或創(chuàng)建)配置文件散怖,如下所示:{ "dns": ["your_dns_address", "8.8.8.8"] }
在上面的示例中,列表的第一個(gè)元素是DNS服務(wù)器的地址肄渗。第二項(xiàng)是Google的DNS镇眷,可在第一項(xiàng)無法使用時(shí)使用。
在繼續(xù)之前恳啥,請保存
daemon.json
并重新啟動(dòng)docker服務(wù)偏灿。
sudo service docker restart
修復(fù)后,重試運(yùn)行該
build
命令钝的。
運(yùn)行該應(yīng)用程序
運(yùn)行應(yīng)用程序翁垂,使用以下方法-p
將計(jì)算機(jī)的端口4000映射到容器的已發(fā)布端口80 :
docker run -p 4000:80 friendlyhello
您應(yīng)該看到Python正在為您的應(yīng)用程序提供服務(wù)的消息http://0.0.0.0:80
。但是該消息來自容器內(nèi)部硝桩,它不知道您將該容器的端口80映射到4000沿猜,從而生成正確的URL http://localhost:4000
。
在Web瀏覽器中轉(zhuǎn)到該URL,以查看在網(wǎng)頁上提供的顯示內(nèi)容芽唇。
注意:如果您在Windows 7上使用Docker Toolbox,請使用Docker Machine IP而不是
localhost
符匾。例如祈坠,http://192.168.99.100:4000 /害碾。要查找IP地址,請使用該命令docker-machine ip
赦拘。
您還可以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
內(nèi)部Dockerfile
和您publish
使用的 內(nèi)容之間的差異docker run -p
。在后面的步驟中躺同,我們只是將主機(jī)上的端口80映射到容器中的端口80并使用http://localhost
阁猜。
點(diǎn)擊CTRL+C
你的終端退出。
在Windows上蹋艺,顯式停止容器
在Windows系統(tǒng)上剃袍,
CTRL+C
不會(huì)停止容器。因此捎谨,首先鍵入CTRL+C
以獲取提示(或打開另一個(gè)shell)民效,然后鍵入docker container ls
以列出正在運(yùn)行的容器,然后docker container stop <Container NAME or ID>
停止容器侍芝。否則研铆,當(dāng)您嘗試在下一步中重新運(yùn)行容器時(shí),會(huì)從守護(hù)程序收到錯(cuò)誤響應(yīng)州叠。
現(xiàn)在讓我們以分離模式在后臺運(yùn)行應(yīng)用程序:
docker run -d -p 4000:80 friendlyhello
您獲得應(yīng)用程序的長容器ID棵红,然后被踢回終端。您的容器正在后臺運(yùn)行咧栗。您還可以看到縮寫的容器ID docker container ls
(并且在運(yùn)行命令時(shí)都可以互換):
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED
1fa4ab2cf395 friendlyhello "python app.py" 28 seconds ago
請注意逆甜,CONTAINER ID
匹配的是什么http://localhost:4000
。
現(xiàn)在docker container stop
用來結(jié)束這個(gè)過程致板,使用CONTAINER ID
如下:
docker container stop 1fa4ab2cf395
分享你的映像
為了演示我們剛剛創(chuàng)建的內(nèi)容的可移植性交煞,讓我們上傳我們構(gòu)建的映像并在其他地方運(yùn)行它。畢竟斟或,當(dāng)您想要將容器部署到生產(chǎn)環(huán)境時(shí)素征,您需要知道如何推送到registry 。
registry 是repositories的集合萝挤,repositories是image的集合 - 類似于GitHub存儲(chǔ)庫御毅,除了代碼已經(jīng)構(gòu)建。registry 上的帳戶可以創(chuàng)建許多repositories怜珍。該docker
CLI默認(rèn)情況下使用Docker的公共registry 端蛆。
注意:我們在這里使用Docker的公共注冊表只是因?yàn)樗敲赓M(fèi)和預(yù)先配置的,但有許多公共注冊表可供選擇酥泛,您甚至可以使用Docker Trusted Registry設(shè)置自己的私有注冊表今豆。
使用您的Docker ID登錄
如果您沒有Docker帳戶嫌拣,請?jiān)?a target="_blank" rel="nofollow">hub.docker.com上注冊一個(gè)帳戶 。記下您的用戶名呆躲。
登錄本地計(jì)算機(jī)上的Docker公共注冊表异逐。
$ docker login
標(biāo)記圖像
將本地映像與注冊表上的存儲(chǔ)庫相關(guān)聯(lián)的表示法是 username/repository:tag
。標(biāo)簽是可選的歼秽,但建議使用应役,因?yàn)樗亲怨芾頇C(jī)構(gòu)用來為Docker鏡像提供版本的機(jī)制。為上下文提供存儲(chǔ)庫和標(biāo)記有意義的名稱燥筷,例如 get-started:part2
。這會(huì)將圖像放入get-started
存儲(chǔ)庫并將其標(biāo)記為part2
院崇。
現(xiàn)在肆氓,把它們放在一起來標(biāo)記圖像。docker tag image
使用您的用戶名底瓣,存儲(chǔ)庫和標(biāo)記名稱運(yùn)行谢揪,以便將圖像上載到所需的目標(biāo)位置。該命令的語法是:
docker tag image username/repository:tag
例如:
docker tag friendlyhello gordon/get-started:part2
運(yùn)行docker image ls以查看新標(biāo)記的圖像捐凭。
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
friendlyhello latest d9e555c53008 3 minutes ago 195MB
gordon/get-started part2 d9e555c53008 3 minutes ago 195MB
python 2.7-slim 1c7128a655f6 5 days ago 183MB
...
發(fā)布圖像
將標(biāo)記的圖像上傳到存儲(chǔ)庫:
docker push username/repository:tag
完成后拨扶,此上傳的結(jié)果將公開發(fā)布。如果您登錄到Docker Hub茁肠,則會(huì)在其中看到新圖像及其pull命令患民。
從遠(yuǎn)程存儲(chǔ)庫中拉出并運(yùn)行映像
從現(xiàn)在開始,您可以使用docker run
以下命令在任何計(jì)算機(jī)上使用和運(yùn)行您的應(yīng)用程序:
docker run -p 4000:80 username/repository:tag
如果映像在計(jì)算機(jī)上不可用垦梆,則Docker會(huì)從存儲(chǔ)庫中提取映像匹颤。
$ docker run -p 4000:80 gordon/get-started:part2
Unable to find image 'gordon/get-started:part2' locally
part2: Pulling from gordon/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 gordon/get-started:part2
* Running on http://0.0.0.0:80/ (Press CTRL+C to quit)
無論在哪里docker run
執(zhí)行,它都會(huì)提取您的圖像托猩,以及Python和所有依賴項(xiàng)requirements.txt
印蓖,并運(yùn)行您的代碼。它們都在一個(gè)整潔的小包中一起旅行京腥,你不需要在主機(jī)上安裝任何東西赦肃,以便Docker運(yùn)行它。
第二部分的結(jié)論
這就是這個(gè)頁面的全部內(nèi)容公浪。在下一節(jié)中他宛,我們將學(xué)習(xí)如何通過在服務(wù)中運(yùn)行此容器來擴(kuò)展應(yīng)用程序。
回顧和備忘單(可選)
以下是此頁面中基本Docker命令的列表因悲,以及一些相關(guān)的命令堕汞,如果您想在繼續(xù)之前稍微探索一下。
docker build -t friendlyhello . # Create image using this directory's Dockerfile
docker run -p 4000:80 friendlyhello # Run "friendlyname" mapping port 4000 to 80
docker run -d -p 4000:80 friendlyhello # 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