Docker入門,第2部分:容器

原文地址:
https://docs.docker.com/get-started/part2/#recap-and-cheat-sheet-optional

預(yù)計(jì)閱讀時(shí)間: 14分鐘

先決條件

介紹

現(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.pyrequirements.txt。讓我們創(chuàng)建下一個(gè)亏较。

應(yīng)用程序本身

再創(chuàng)建兩個(gè)文件莺褒,requirements.txt然后app.py將它們放在Dockerfile的同一個(gè)文件夾中。這完成了我們的應(yīng)用程序雪情,您可以看到它非常簡單遵岩。當(dāng)上述Dockerfile被build進(jìn)映像,app.pyrequirements.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)容芽唇。

瀏覽器中的Hello World

注意:如果您在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怜珍。該dockerCLI默認(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)用程序。

繼續(xù)閱讀第3部分>>

回顧和備忘單(可選)

是本頁所涵蓋內(nèi)容的終端錄音

以下是此頁面中基本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

容器晃琳,python讯检,代碼琐鲁,編碼構(gòu)建人灼,推送围段,運(yùn)行

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市投放,隨后出現(xiàn)的幾起案子奈泪,更是在濱河造成了極大的恐慌,老刑警劉巖灸芳,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件涝桅,死亡現(xiàn)場離奇詭異,居然都是意外死亡烙样,警方通過查閱死者的電腦和手機(jī)冯遂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來谒获,“玉大人蛤肌,你說我怎么就攤上這事∨” “怎么了裸准?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長赔硫。 經(jīng)常有香客問我炒俱,道長,這世上最難降的妖魔是什么卦停? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任向胡,我火速辦了婚禮,結(jié)果婚禮上惊完,老公的妹妹穿的比我還像新娘僵芹。我一直安慰自己,他們只是感情好小槐,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布拇派。 她就那樣靜靜地躺著,像睡著了一般凿跳。 火紅的嫁衣襯著肌膚如雪件豌。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天控嗜,我揣著相機(jī)與錄音茧彤,去河邊找鬼。 笑死疆栏,一個(gè)胖子當(dāng)著我的面吹牛曾掂,可吹牛的內(nèi)容都是我干的惫谤。 我是一名探鬼主播,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼珠洗,長吁一口氣:“原來是場噩夢啊……” “哼溜歪!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起许蓖,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蝴猪,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后膊爪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體自阱,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年米酬,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了动壤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,841評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡淮逻,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出阁簸,到底是詐尸還是另有隱情爬早,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布启妹,位于F島的核電站筛严,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏饶米。R本人自食惡果不足惜桨啃,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望檬输。 院中可真熱鬧照瘾,春花似錦、人聲如沸丧慈。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽逃默。三九已至鹃愤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間完域,已是汗流浹背软吐。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留吟税,地道東北人凹耙。 一個(gè)月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓姿现,卻偏偏與公主長得像,于是被迫代替她去往敵國和親使兔。 傳聞我的和親對象是個(gè)殘疾皇子建钥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評論 2 354

推薦閱讀更多精彩內(nèi)容