我們?cè)诶斫?docker
之前爷绘,首先我們得先區(qū)分清楚兩個(gè)概念,容器和虛擬機(jī)岗钩。
可能很多讀者朋友都用過(guò)虛擬機(jī)胞谈,而對(duì)容器這個(gè)概念比較的陌生尘盼。
我們用的傳統(tǒng)虛擬機(jī)如 VMware
憨愉, VisualBox
之類的需要模擬整臺(tái)機(jī)器包括硬件,每臺(tái)虛擬機(jī)都需要有自己的操作系統(tǒng)卿捎,虛擬機(jī)一旦被開啟配紫,預(yù)分配給它的資源將全部被占用。每一臺(tái)虛擬機(jī)包括應(yīng)用午阵,必要的二進(jìn)制和庫(kù)躺孝,以及一個(gè)完整的用戶操作系統(tǒng)。
而容器技術(shù)是和我們的宿主機(jī)共享硬件資源及操作系統(tǒng)底桂,可以實(shí)現(xiàn)資源的動(dòng)態(tài)分配植袍。容器包含應(yīng)用和其所有的依賴包,但是與其他容器共享內(nèi)核籽懦。容器在宿主機(jī)操作系統(tǒng)中于个,在用戶空間以分離的進(jìn)程運(yùn)行。
容器技術(shù)是實(shí)現(xiàn)操作系統(tǒng)虛擬化的一種途徑猫十,可以讓您在資源受到隔離的進(jìn)程中運(yùn)行應(yīng)用程序及其依賴關(guān)系览濒。通過(guò)使用容器,我們可以輕松打包應(yīng)用程序的代碼拖云、配置和依賴關(guān)系,將其變成容易使用的構(gòu)建塊应又,從而實(shí)現(xiàn)環(huán)境一致性运翼、運(yùn)營(yíng)效率惑朦、開發(fā)人員生產(chǎn)力和版本控制等諸多目標(biāo)。容器可以幫助保證應(yīng)用程序快速、可靠您朽、一致地部署,其間不受部署環(huán)境的影響卵皂。容器還賦予我們對(duì)資源更多的精細(xì)化控制能力肾胯,讓我們的基礎(chǔ)設(shè)施效率更高。通過(guò)下面這幅圖我們可以很直觀的反映出這兩者的區(qū)別所在旬蟋。
Docker 屬于 Linux 容器的一種封裝油昂,提供簡(jiǎn)單易用的容器使用接口。它是目前最流行的 Linux
容器解決方案倾贰。
而 Linux
容器是 Linux
發(fā)展出了另一種虛擬化技術(shù)冕碟,簡(jiǎn)單來(lái)講, Linux
容器不是模擬一個(gè)完整的操作系統(tǒng)匆浙,而是對(duì)進(jìn)程進(jìn)行隔離安寺,相當(dāng)于是在正常進(jìn)程的外面套了一個(gè)保護(hù)層。對(duì)于容器里面的進(jìn)程來(lái)說(shuō)首尼,它接觸到的各種資源都是虛擬的挑庶,從而實(shí)現(xiàn)與底層系統(tǒng)的隔離言秸。
Docker
將應(yīng)用程序與該程序的依賴,打包在一個(gè)文件里面迎捺。運(yùn)行這個(gè)文件井仰,就會(huì)生成一個(gè)虛擬容器。程序在這個(gè)虛擬容器里運(yùn)行破加,就好像在真實(shí)的物理機(jī)上運(yùn)行一樣俱恶。有了 Docker
,就不用擔(dān)心環(huán)境問(wèn)題范舀。
總體來(lái)說(shuō)合是, Docker
的接口相當(dāng)簡(jiǎn)單,用戶可以方便地創(chuàng)建和使用容器锭环,把自己的應(yīng)用放入容器聪全。容器還可以進(jìn)行版本管理、復(fù)制辅辩、分享难礼、修改,就像管理普通的代碼一樣玫锋。
Docker的優(yōu)勢(shì)
Docker相比于傳統(tǒng)虛擬化方式具有更多的優(yōu)勢(shì):
-
docker
啟動(dòng)快速屬于秒級(jí)別蛾茉。虛擬機(jī)通常需要幾分鐘去啟動(dòng) -
docker
需要的資源更少,docker
在操作系統(tǒng)級(jí)別進(jìn)行虛擬化撩鹿,docker
容器和內(nèi)核交互谦炬,幾乎沒(méi)有性能損耗,性能優(yōu)于通過(guò)Hypervisor
層與內(nèi)核層的虛擬化 -
docker
更輕量节沦,docker
的架構(gòu)可以共用一個(gè)內(nèi)核與共享應(yīng)用程序庫(kù)键思,所占內(nèi)存極小。同樣的硬件環(huán)境甫贯,Docker
運(yùn)行的鏡像數(shù)遠(yuǎn)多于虛擬機(jī)數(shù)量吼鳞,對(duì)系統(tǒng)的利用率非常高 - 與虛擬機(jī)相比,
docker
隔離性更弱叫搁,docker
屬于進(jìn)程之間的隔離赔桌,虛擬機(jī)可實(shí)現(xiàn)系統(tǒng)級(jí)別隔離 - 安全性:
docker
的安全性也更弱。Docker
的租戶root
和宿主機(jī)root
等同常熙,一旦容器內(nèi)的用戶從普通用戶權(quán)限提升為root權(quán)限纬乍,它就直接具備了宿主機(jī)的root權(quán)限,進(jìn)而可進(jìn)行無(wú)限制的操作裸卫。虛擬機(jī)租戶root
權(quán)限和宿主機(jī)的root
虛擬機(jī)權(quán)限是分離的仿贬,并且虛擬機(jī)利用如Intel
的VT-d
和VT-x
的ring-1
硬件隔離技術(shù),這種隔離技術(shù)可以防止虛擬機(jī)突破和彼此交互墓贿,而容器至今還沒(méi)有任何形式的硬件隔離茧泪,這使得容器容易受到攻擊 - 可管理性:
docker
的集中化管理工具還不算成熟蜓氨。各種虛擬化技術(shù)都有成熟的管理工具,例如VMware vCenter
提供完備的虛擬機(jī)管理能力 - 高可用和可恢復(fù)性:
docker
對(duì)業(yè)務(wù)的高可用支持是通過(guò)快速重新部署實(shí)現(xiàn)的队伟。虛擬化具備負(fù)載均衡穴吹,高可用,容錯(cuò)嗜侮,遷移和數(shù)據(jù)保護(hù)等經(jīng)過(guò)生產(chǎn)實(shí)踐檢驗(yàn)的成熟保障機(jī)制港令,VMware
可承諾虛擬機(jī)99.999%
高可用,保證業(yè)務(wù)連續(xù)性 - 快速創(chuàng)建锈颗、刪除:虛擬化創(chuàng)建是分鐘級(jí)別的顷霹,
Docker
容器創(chuàng)建是秒級(jí)別的,Docker
的快速迭代性击吱,決定了無(wú)論是開發(fā)淋淀、測(cè)試、部署都可以節(jié)約大量時(shí)間 - 交付覆醇、部署:虛擬機(jī)可以通過(guò)鏡像實(shí)現(xiàn)環(huán)境交付的一致性朵纷,但鏡像分發(fā)無(wú)法體系化。
Docker
在Dockerfile
中記錄了容器構(gòu)建過(guò)程永脓,可在集群中實(shí)現(xiàn)快速分發(fā)和快速部署
我們可以從下面這張表格很清楚地看到容器相比于傳統(tǒng)虛擬機(jī)的特性的優(yōu)勢(shì)所在:
特性 | 容器 | 虛擬機(jī) |
---|---|---|
啟動(dòng) | 秒級(jí) | 分鐘級(jí) |
硬盤使用 | 一般為MB | 一般為GB |
性能 | 接近原生 | 弱于 |
系統(tǒng)支持量 | 單機(jī)支持上千個(gè)容器 | 一般是幾十個(gè) |
Docker的三個(gè)基本概念
從上圖我們可以看到袍辞,Docker 中包括三個(gè)基本的概念:
- Image(鏡像)
- Container(容器)
- Repository(倉(cāng)庫(kù))
鏡像是 Docker 運(yùn)行容器的前提,倉(cāng)庫(kù)是存放鏡像的場(chǎng)所憨奸,可見(jiàn)鏡像更是 Docker 的核心革屠。
Image (鏡像)
那么鏡像到底是什么呢?
Docker
鏡像可以看作是一個(gè)特殊的文件系統(tǒng)排宰,除了提供容器運(yùn)行時(shí)所需的程序、庫(kù)那婉、資源板甘、配置等文件外,還包含了一些為運(yùn)行時(shí)準(zhǔn)備的一些配置參數(shù)(如匿名卷详炬、環(huán)境變量盐类、用戶等)。鏡像不包含任何動(dòng)態(tài)數(shù)據(jù)呛谜,其內(nèi)容在構(gòu)建之后也不會(huì)被改變在跳。
鏡像(Image)
就是一堆只讀層(read-only layer)
的統(tǒng)一視角,也許這個(gè)定義有些難以理解隐岛,下面的這張圖能夠幫助讀者理解鏡像的定義猫妙。
從左邊我們看到了多個(gè)只讀層,它們重疊在一起聚凹。除了最下面一層割坠,其它層都會(huì)有一個(gè)指針指向下一層齐帚。這些層是Docker
內(nèi)部的實(shí)現(xiàn)細(xì)節(jié),并且能夠在主機(jī)的文件系統(tǒng)上訪問(wèn)到彼哼。統(tǒng)一文件系統(tǒng) (union file system)
技術(shù)能夠?qū)⒉煌膶诱铣梢粋€(gè)文件系統(tǒng)对妄,為這些層提供了一個(gè)統(tǒng)一的視角,這樣就隱藏了多層的存在敢朱,在用戶的角度看來(lái)剪菱,只存在一個(gè)文件系統(tǒng)。我們可以在圖片的右邊看到這個(gè)視角的形式拴签。
Container (容器)
容器 (container)
的定義和鏡像 (image)
幾乎一模一樣孝常,也是一堆層的統(tǒng)一視角,唯一區(qū)別在于容器的最上面那一層是可讀可寫的篓吁。
由于容器的定義并沒(méi)有提及是否要運(yùn)行容器茫因,所以實(shí)際上,容器 = 鏡像 + 讀寫層杖剪。
Repository (倉(cāng)庫(kù))
Docker
倉(cāng)庫(kù)是集中存放鏡像文件的場(chǎng)所冻押。鏡像構(gòu)建完成后,可以很容易的在當(dāng)前宿主上運(yùn)行盛嘿,但是洛巢, 如果需要在其它服務(wù)器上使用這個(gè)鏡像,我們就需要一個(gè)集中的存儲(chǔ)次兆、分發(fā)鏡像的服務(wù)稿茉,Docker Registry
(倉(cāng)庫(kù)注冊(cè)服務(wù)器)就是這樣的服務(wù)。有時(shí)候會(huì)把倉(cāng)庫(kù) (Repository)
和倉(cāng)庫(kù)注冊(cè)服務(wù)器 (Registry)
混為一談芥炭,并不嚴(yán)格區(qū)分漓库。Docker
倉(cāng)庫(kù)的概念跟 Git
類似,注冊(cè)服務(wù)器可以理解為 GitHub
這樣的托管服務(wù)园蝠。實(shí)際上渺蒿,一個(gè) Docker Registry
中可以包含多個(gè)倉(cāng)庫(kù) (Repository)
,每個(gè)倉(cāng)庫(kù)可以包含多個(gè)標(biāo)簽 (Tag)
彪薛,每個(gè)標(biāo)簽對(duì)應(yīng)著一個(gè)鏡像茂装。所以說(shuō),鏡像倉(cāng)庫(kù)是 Docker
用來(lái)集中存放鏡像文件的地方類似于我們之前常用的代碼倉(cāng)庫(kù)善延。
通常少态,一個(gè)倉(cāng)庫(kù)會(huì)包含同一個(gè)軟件不同版本的鏡像,而標(biāo)簽就常用于對(duì)應(yīng)該軟件的各個(gè)版本 易遣。我們可以通過(guò)<倉(cāng)庫(kù)名>:<標(biāo)簽>
的格式來(lái)指定具體是這個(gè)軟件哪個(gè)版本的鏡像彼妻。如果不給出標(biāo)簽,將以 latest
作為默認(rèn)標(biāo)簽.训挡。
倉(cāng)庫(kù)又可以分為兩種形式:
-
public
(公有倉(cāng)庫(kù)) -
private
(私有倉(cāng)庫(kù))
Docker Registry
公有倉(cāng)庫(kù)是開放給用戶使用澳骤、允許用戶管理鏡像的 Registry
服務(wù)歧强。一般這類公開服務(wù)允許用戶免費(fèi)上傳、下載公開的鏡像为肮,并可能提供收費(fèi)服務(wù)供用戶管理私有鏡像摊册。
除了使用公開服務(wù)外,用戶還可以在本地搭建私有 Docker Registry
颊艳。Docker
官方提供了 Docker Registry
鏡像茅特,可以直接使用做為私有 Registry
服務(wù)。當(dāng)用戶創(chuàng)建了自己的鏡像之后就可以使用 push
命令將它上傳到公有或者私有倉(cāng)庫(kù)棋枕,這樣下次在另外一臺(tái)機(jī)器上使用這個(gè)鏡像時(shí)候白修,只需要從倉(cāng)庫(kù)上 pull
下來(lái)就可以了。
我們主要把 Docker
的一些常見(jiàn)概念如 Image
重斑, Container
兵睛, Repository
做了詳細(xì)的闡述,也從傳統(tǒng)虛擬化方式的角度闡述了 docker
的優(yōu)勢(shì)窥浪,我們從下圖可以直觀地看到 Docker
的架構(gòu):
Docker
使用 C/S
結(jié)構(gòu)祖很,即客戶端/服務(wù)器體系結(jié)構(gòu)。 Docker
客戶端與 Docker
服務(wù)器進(jìn)行交互漾脂,Docker服務(wù)端負(fù)責(zé)構(gòu)建假颇、運(yùn)行和分發(fā) Docker
鏡像。 Docker
客戶端和服務(wù)端可以運(yùn)行在一臺(tái)機(jī)器上骨稿,也可以通過(guò) RESTful
笨鸡、 stock
或網(wǎng)絡(luò)接口與遠(yuǎn)程 Docker
服務(wù)端進(jìn)行通信。
這張圖展示了 Docker
客戶端坦冠、服務(wù)端和 Docker
倉(cāng)庫(kù)(即 Docker Hub
和 Docker Cloud
)形耗,默認(rèn)情況下Docker
會(huì)在 Docker
中央倉(cāng)庫(kù)尋找鏡像文件,這種利用倉(cāng)庫(kù)管理鏡像的設(shè)計(jì)理念類似于 Git
辙浑,當(dāng)然這個(gè)倉(cāng)庫(kù)是可以通過(guò)修改配置來(lái)指定的趟脂,甚至我們可以創(chuàng)建我們自己的私有倉(cāng)庫(kù)。
Docker的安裝
Docker Platform
- Docker提供了一個(gè)開發(fā)例衍、打包、運(yùn)行app的平臺(tái)
-
Docker把a(bǔ)pp和底層infrastructure隔離開來(lái)
Docker Engine
Docker Engine是一個(gè)C/S架構(gòu)的應(yīng)用程序已卸,主要包含下面幾個(gè)組件佛玄;
- 常駐后臺(tái)進(jìn)程Dockerd
- 一個(gè)用來(lái)和Dockerd交互的REST API Server
-
命令行CLI接口,通過(guò)和REST API進(jìn)行交互
Docker架構(gòu)
Docker 的核心組件包括:
- Docker Client
- Docker daemon
- Docker Image
- Docker Registry
- Docker Container
Docker Damon
Docker Damon來(lái)監(jiān)聽(tīng)Docker API的請(qǐng)求和管理Docker對(duì)象累澡,比如鏡像梦抢、容器、網(wǎng)絡(luò)和Volume愧哟。
Docker Client
docker client是我們和Docker進(jìn)行交互的最主要的方式方法奥吩,比如可以通過(guò)docker run來(lái)運(yùn)行一個(gè)容器哼蛆,然后我們的這個(gè)client會(huì)把命令發(fā)送給上面的Docker。
Docker Registry
Docker Registry 用來(lái)存儲(chǔ)Docker鏡像的倉(cāng)庫(kù)霞赫,Docker Hub是Docker官方提供的一個(gè)公共倉(cāng)庫(kù)腮介,而且Docker默認(rèn)也是從Docker Hub上查找鏡像的,當(dāng)然你也可以很方便的運(yùn)行一個(gè)私有倉(cāng)庫(kù)端衰,當(dāng)我們使用docker pull或者docker run命令時(shí)叠洗,就會(huì)從我們配置的Docker鏡像倉(cāng)庫(kù)中去拉取鏡像,使用docker push命令時(shí)旅东,會(huì)將我們構(gòu)建的鏡像推送到對(duì)應(yīng)的鏡像倉(cāng)庫(kù)中灭抑。
Images 鏡像
鏡像是一個(gè)制度模板,帶有Docker容器的說(shuō)明抵代。一般來(lái)說(shuō)的腾节,鏡像會(huì)基于另外的一些基礎(chǔ)鏡像上面安裝一個(gè)Nginx服務(wù)器,這樣就可以構(gòu)建一個(gè)屬于我們自己的鏡像了荤牍。
Containers 容器
容器是一個(gè)鏡像的可運(yùn)行的實(shí)例案腺,可以使用Docker REST API或者CLI來(lái)操作容器,容器的實(shí)質(zhì)是進(jìn)程参淫,但與直接在宿主執(zhí)行的實(shí)例進(jìn)程不同救湖,容器進(jìn)程屬于自己的獨(dú)立的命名空間。因此容器可以擁有自己的root文件系統(tǒng)涎才、自己的網(wǎng)絡(luò)配置鞋既、自己的進(jìn)程空間、甚至自己的用戶ID耍铜。容器內(nèi)的經(jīng)常是運(yùn)行在一個(gè)隔離的環(huán)境里邑闺,使用起來(lái),就好像在一個(gè)獨(dú)立于宿主的系統(tǒng)下操作一樣棕兼。這種特性使得容器封裝的應(yīng)用比直接在宿主運(yùn)行更加安全陡舅。
Docker底層的技術(shù)支持
Namespaces:做隔離pid、net伴挚、ipc靶衍、mnt、uts
Control groups:做資源限制
Union file systems:Container和image的分層
Docker Image概述
- 文件和meta data的集合(root filesystem)
- 分層的茎芋,并且每一層都可以添加颅眶、改變和刪除文件,成為一個(gè)新的image
- 不同的image可以共享相同的layer
-
Image本身是read-only的
Docker技術(shù)里最為基礎(chǔ)的兩大概念:鏡像和容器田弥。
鏡像的獲取方式:
- 從registry拉取
- 從Dockerfile構(gòu)建
搜索鏡像
docker search <image> # 在docker index中搜索image
--automated=false 僅顯示自動(dòng)創(chuàng)建的鏡像
--no-trunc=false 輸出信息不截?cái)囡@示
-s 0 指定僅顯示評(píng)價(jià)為指定星級(jí)的鏡像
下載鏡像
docker pull <image> # 從docker registry server 中下拉image
還可通過(guò)指定標(biāo)簽下載某鏡像
docker pull [:TAG]
docker pull centos:7
查看鏡像/刪除
docker images: # 列出images
docker images -a # 列出所有的images(包含歷史)
docker ps -a #列出本機(jī)所有容器
docker rmi <image ID>: # 刪除一個(gè)或多個(gè)image
存出和載入鏡像
存出本地鏡像文件為.tar
docker save -o ubuntu_14.04.tar ubuntu:14.04
導(dǎo)入鏡像到本地鏡像庫(kù)
docker load --input ubuntu_14.04.tar或者
docker load < ubuntu_14.04.tar
上傳鏡像
用戶在dockerhub網(wǎng)站注冊(cè)后涛酗,即可上傳自制的鏡像。
docker push NAME[:TAG]
Container容器
- 通過(guò)Image創(chuàng)建(copy)
- 在Image layer之上建立一個(gè)container layer(可讀寫)
- 類比Java面向?qū)ο螅侯惡蛯?shí)例
-
Image負(fù)責(zé)app的存儲(chǔ)和分發(fā),Container負(fù)責(zé)運(yùn)行app
創(chuàng)建(使用鏡像創(chuàng)建容器):
首先得查看鏡像的REPOSITORY和TAG
docker run -i -t REPOSITORY:TAG (等價(jià)于先執(zhí)行docker create 再執(zhí)行docker start 命令)
其中-t選項(xiàng)讓docker分配一個(gè)偽終端并綁定到容器的標(biāo)準(zhǔn)輸入上商叹, -i則讓容器的標(biāo)準(zhǔn)輸入保持打開燕刻。若要在后臺(tái)以守護(hù)態(tài)(daemonized)形式運(yùn)行,可加參數(shù)-d
在執(zhí)行docker run來(lái)創(chuàng)建并啟動(dòng)容器時(shí)剖笙,后臺(tái)運(yùn)行的標(biāo)準(zhǔn)包括:
- 檢查本地是否存在指定的鏡像卵洗,不存在就從公有倉(cāng)庫(kù)下載
- 利用鏡像創(chuàng)建并啟動(dòng)一個(gè)容器
- 分配一個(gè)文件系統(tǒng),并在只讀的鏡像層外面掛載一層可讀可寫層
- 從宿主機(jī)配置的網(wǎng)橋接口中橋接一個(gè)虛擬接口到容器
- 從地址池配置一個(gè)ip地址給容器
- 執(zhí)行用戶指定的應(yīng)用程序
- 執(zhí)行完畢后容器被終止
docker start/stop/restart <container> #:開啟/停止/重啟container
進(jìn)入容器:
docker attach [container_id] #連接一個(gè)正在運(yùn)行的container實(shí)例(即實(shí)例須為start狀態(tài)枯途,可以多個(gè) 窗口同時(shí)attach 一個(gè)container實(shí)例)忌怎,但當(dāng)某個(gè)窗口因命令阻塞時(shí),其它窗口也無(wú)法執(zhí)行了酪夷。
exec可直接在容器內(nèi)運(yùn)行的命令榴啸。docker exec -ti [container_id] /bin/bash
刪除容器:
docker rm <container...> #:刪除一個(gè)或多個(gè)container
docker rm `docker ps -a -q` #:刪除所有的container
docker ps -a -q | xargs docker rm #:同上, 刪除所有的container
docker -rm
-f 強(qiáng)制中止并運(yùn)行的容器
-l 刪除容器的連接,但保留容器
-v 刪除容器掛載的數(shù)據(jù)卷
修改容器:
docker commit <container> [repo:tag] # 將一個(gè)container固化為一個(gè)新的image晚岭,后面的repo:tag可選鸥印。
導(dǎo)入和導(dǎo)出容器:
導(dǎo)出到一個(gè)文件,不管是否處于運(yùn)行狀態(tài)坦报。
docker export CONTAINER > test.tar
導(dǎo)入為鏡像:
cat test.tar | docker import - centos:latest
Dockerfile語(yǔ)法梳理及最佳實(shí)踐
一库说、 FROM
Syntax:
FROM <image>[:<tag> | @<digest>] [AS <name>]
FROM指定一個(gè)基礎(chǔ)鏡像,且必須為Dockerfile文件開篇的每個(gè)非注釋行,至于image則可以是任何合理存在的image鏡像
FROM可以在一個(gè)Dockerfile中出現(xiàn)多次片择,以便于創(chuàng)建混合的images潜的。如果沒(méi)有指定tag,latest將會(huì)被指定為要使用的基礎(chǔ)鏡像版本。
AS name,可以給新的構(gòu)建階段賦予名稱字管。該名稱可用于后續(xù)FROM 和 COPY --from=<name | index>說(shuō)明可以引用此階段中構(gòu)建的鏡像
- 為了安全啰挪,盡量使用官方的image作為base image
二、LABEL
為鏡像生成元數(shù)據(jù)標(biāo)簽信息
Syntax:
LABEL <KEY>=<VALUE> \
<KEY>="XXXX"
多個(gè)標(biāo)簽寫成一行嘲叔,避免在鏡像中額外增加layer
三亡呵、MAINTAINER
作者信息,寫在FROM后
Syntax:
MAINTAINER "auth <email>"
四、COPY
當(dāng)復(fù)制一個(gè)目錄時(shí)硫戈,并不會(huì)復(fù)制目錄本身锰什,而是會(huì)遞歸復(fù)制其下子目錄 至目標(biāo)目錄下
Syntax:
COPY data /data/
文件復(fù)制準(zhǔn)則
- <src>必須是build上下言文中的路徑,不能是其父目錄中的文件
- 如果<src>是目錄丁逝,則其內(nèi)部文件或子目錄會(huì)被遞歸復(fù)制汁胆,但<src>目錄自身不會(huì)被復(fù)制
- 如果指定了多個(gè)<src>,或在<src>中使用了通配符,則<dest>必須是一個(gè)目錄霜幼,且必須以/結(jié)尾
- 如果<dest>事先不存在沦泌,它將會(huì)被自動(dòng)創(chuàng)建,這包括其父目錄路徑辛掠。
五、ADD
ADD指令類似于COPY指令,ADD支持使用TAR文件和URL路徑
Syntax:
ADD <src>...<dest>
ADD ["<src>",..."<dest>"]
操作準(zhǔn)則:
- 如果<src>為URL且<dest>不以/結(jié)尾萝衩,則<src>指定的文件將被下載并直接被創(chuàng)建為<dest>;如果<dest>以/結(jié)尾回挽,則文件名URL指定的文件將被直接下載并保存為<dest>/<filename>
- 如果<src>是一個(gè)本地文件系統(tǒng)上的壓縮格式的tar文件,它將被展開為一個(gè)目錄猩谊,其行為類似于"tar -x"命令;然而千劈,通過(guò)URL獲取到的tar文件將不會(huì)自動(dòng)展開。
- 如果<src>有多個(gè)牌捷,或其間接或直接使用了通配符墙牌,則<dest>必須是一個(gè)以/結(jié)尾的目錄路徑;如果<dest>不以/結(jié)尾,則其被視作一個(gè)普通文件暗甥,<src>內(nèi)容將被直接寫入到<dest>
- 為了讓鏡像盡量小喜滨,最好不要使用 ADD 指令從遠(yuǎn)程 URL 獲取包,而是使用 curl 和 wget撤防。這樣你可以在文件提取完之后刪掉不再需要的文件來(lái)避免在鏡像中額外添加一層虽风。
示例:
額外操作:
ADD http://example.com/1.tar.gz /apps/
RUN tar xf /apps/1.tar.gz -C /apps/ && \
/bin/sh -c /apps/***.sh
簡(jiǎn)單操作:
RUN mkdir -p /iyunwen/server/ && \
curl -SL http://example.com/1.tar.gz \
| tar -xzC /iyunwen/server/ && \
/bin/sh -c /apps/***.sh
注意:
大部分情況下,COPY由于ADD
ADD除了COPY外還有額外解壓縮功能
添加遠(yuǎn)程文件 / 目錄寄月,請(qǐng)使用curl或者wget
六辜膝、WORKDIR
用于為Dockerfile中所有RUN、CMD漾肮、ENTRYPOINT厂抖、COPY和ADD指令設(shè)定工作目錄
注意:
- 用WORKDIR,不要用RUN cd
- 盡量使用絕對(duì)目錄
Syntax:
WORKDIR <dirpath>
在Dockerfile文件中克懊,WORKDIR指令可以出現(xiàn)多次忱辅,其路徑也可以為相對(duì)路徑,不過(guò)保檐,其是相對(duì)此前一個(gè)WORKDIR指令指定的路徑
另外耕蝉,WORKDIR也可調(diào)用由ENV指定定義的變量
ex:
WORKDIR /var/log
WORKDIR $STATEPATH
七、RUN
接受命令作為參數(shù)并用于創(chuàng)建鏡像,在之前的commit層上形成新的層夜只。
注意:
- 為了美觀垒在,復(fù)雜的RUN請(qǐng)用反斜線換行
- 避免無(wú)用分層,合并多條命令成一行
Syntax:
RUN \<command\>(如同執(zhí)行shell命令 /bin/sh -c)
RUN ["executable","param1","param2"]
- RUN 指令將在當(dāng)前image中執(zhí)行任意合法命令并提交執(zhí)行結(jié)果扔亥。命令執(zhí)行提交后场躯,就會(huì)自動(dòng)執(zhí)行Dockerfile中的下一個(gè)指令。
- 分層RUN指令和生成提交符合Docker的核心概念旅挤,其中提交很輕量踢关,可以從image將用于Dockerfile中的下一步。
- exec形式使得可以避免shell字符串變化粘茄,以及使用不包含指定的shell可執(zhí)行文件的基本image來(lái)運(yùn)行RUN命令签舞。
- 在shell形式中秕脓,可以使用\(反斜杠)將單個(gè)RUN指令繼續(xù)到下一行。例如:
RUN yum install -y \ openssl \ pcre-devel \ zlib
- 第二種語(yǔ)法格式中的參數(shù)是一個(gè)JSON格式的數(shù)組儒搭,其中<executable>為要運(yùn)行的命令吠架,后面的<paramN>為傳遞給命令的選項(xiàng)或?qū)?shù);然而,此種格式指定的命令不會(huì)以"/bin/sh -c"來(lái)發(fā)起搂鲫,因此常見(jiàn)的shell操作如變量替換以及通配符(?,*等)替換將不會(huì)進(jìn)行;不過(guò)傍药,如果要運(yùn)行的命令依賴于此shell特性的話,可以將其替換為類似下面的格式魂仍。
RUN ["/bin/bash","-c","<executable>","<param1>"]
RUN 指令的緩存在下一次構(gòu)建期間不會(huì)自動(dòng)失效拐辽。用于諸如:yum repolist 之類的指令的緩存將在下一次構(gòu)建期間被重用〔磷茫可以通過(guò)--no-cache 參數(shù)來(lái)使RUN指令的緩存無(wú)效俱诸,例如: docker build --no-cache
管理命令
某些RUN 命令依賴于使用管道字符( | )將管道輸出到另一個(gè)命令功能
RUN wget -O - http://www.baidu.com/index.html | wc -l > /app/html/baidu.html
Docker使用 /bin/sh -c 解釋執(zhí)行這些命令,解釋器只評(píng)估管道中最后一個(gè)操作的退出代碼以確定成功仑氛。在上面的例子中乙埃,只要wc -l 命令成功,即使wget 命令失敗锯岖,該構(gòu)建步驟也會(huì)成功并生成新的鏡像介袜。
由于管道中任何階段的錯(cuò)誤而導(dǎo)致命令失敗,請(qǐng)預(yù)先 set -o pipefail && 確保意外錯(cuò)誤可防止構(gòu)建無(wú)意中成功出吹。例如:
set -o pipefail : 表示在管道連接的命令序列中遇伞,只要有任何一個(gè)命令返回非0值,則整個(gè)管道返回非0值捶牢,即使最后一個(gè)命令返回0.
RUN set -o pipefail && wget -O - http://www.baidu.com/index.html | wc -l > /app/html/baidu.html
注意:
并非所有的shell都支持 -o pipefail 選項(xiàng)鸠珠。在這種情況下(例如 dash shell,這是基于Debian的映像上的默認(rèn)shell)秋麸,請(qǐng)考慮使用exec形式RUN來(lái)明確選擇一個(gè)支持該pipefail選項(xiàng)的shell渐排。如:
RUN ["/bin/bash","-c","set -o pipefail && wget -O - http://www.baidu.com/index.html | wc -l > /app/html/baidu.html"]
八、CMD
類似于RUN指令灸蟆,CMD指令也可用于運(yùn)行任何命令或應(yīng)用程序驯耻,不過(guò),二者的運(yùn)行時(shí)間點(diǎn)不同
- RUN 指令運(yùn)行于映像文件構(gòu)建過(guò)程中炒考,而CMD指令運(yùn)行于基于Dockerfile構(gòu)建出的新鏡像文件啟動(dòng)一個(gè)容器時(shí)可缚。
- CMD指令的首要目的在于為啟動(dòng)的容器指定默認(rèn)要運(yùn)行的程序,且其運(yùn)行結(jié)束后斋枢,容器也將終止;不過(guò)帘靡,CMD指定的命令其可以被docker run的命令行選項(xiàng)所覆蓋
- 在Dockerfile中可以存在多個(gè)CMD指令,但僅最后一個(gè)生效
Syntax:
CMD <command> //支持命令展開瓤帚,但是不支持傳遞信號(hào)
CMD ["<executable>","<param1>","<param2>"] //相當(dāng)于容器的第一個(gè)命令描姚,可以接受信號(hào)
CMD ["param1","param2"]
前兩種語(yǔ)法格式的意義同RUN
第三種則用于為ENTRYPOINT指令提供默認(rèn)參數(shù)
CMD會(huì)在啟動(dòng)容器的時(shí)候執(zhí)行涩赢,build時(shí)不執(zhí)行,而RUN只是在構(gòu)建鏡像的時(shí)候執(zhí)行轰胁,后續(xù)鏡像構(gòu)建完成之后谒主,啟動(dòng)容器就與RUN無(wú)關(guān)了。這個(gè)命令就相當(dāng)于在/etc/rc.d/rc.local中寫命令
九赃阀、ENTRYPOINT
類似CMD指令的功能,用于為容器指定默認(rèn)運(yùn)行程序擎颖,從而使得容器像是一具單獨(dú)的可執(zhí)行程序
與CMD不同的是榛斯,由ENTRYPOINT啟動(dòng)的程序不會(huì)被docker run命令行指定的參數(shù)所覆蓋,而且搂捧,這些命令行參數(shù)會(huì)被當(dāng)作參數(shù)傳遞給ENTRYPOINT指定的程序驮俗。不過(guò),docker run 命令的--entrypoint 選項(xiàng)的參數(shù)可覆蓋ENTRYPOINT指令指定的程序
Syntax:
ENTRYPOINT <command> //這種方式能接受shell命令行展開
ENTRYPOINT ["<executable>","param1"] //展開不了允跑,但能接收到信號(hào)
docker run命令傳入的命令參數(shù)會(huì)覆蓋CMD指令的內(nèi)容并且附加到ENTRYPOINT命令最后做為其參數(shù)使用王凑。Dockerfile文件中也可以存在多個(gè)ENTRYPOINT指令,但僅有最后一個(gè)會(huì)生效
十聋丝、EXPOSE
用來(lái)指定端口索烹,使容器內(nèi)的應(yīng)用可以通過(guò)端口和外界交互。
Syntax:
EXPOSE <port> [<port>...]
告訴Docker服務(wù)端容器對(duì)外映射的本地端口弱睦,需要在docker run 的時(shí)候使用-p 或者 -P 選項(xiàng)生效百姓。
EXPOSE 80/tcp
十一齐媒、ENV
ENV指令可以用于docker容器設(shè)置環(huán)境變量
Syntax:
ENV <key> <value>
ENV <key>=<value> ...
指定一個(gè)環(huán)境變量蛤奢,會(huì)被后續(xù)RUN指令使用,并在容器運(yùn)行時(shí)保留荣恐。
ENV設(shè)置的環(huán)境變量火惊,可以使用 docker inspect 命令來(lái)查看求类。同時(shí)還可以使用 docker run --env <key>=<value>來(lái)修改環(huán)境變量
盡量使用ENV增加可維護(hù)性
十二、USER
用于指定運(yùn)行image時(shí)的或運(yùn)行Dockerfile中任何RUN屹耐、CMD或ENTRYPOINT指令指定的程序時(shí)的用戶名或UID
默認(rèn)情況下尸疆,container的運(yùn)行身份為root用戶
Syntax:
USER <UID>|<UserName>
需要注意的是,<UID>可以為任意數(shù)字,但實(shí)踐中其必須為/etc/passwd中某用戶的有效UID张症,否則,docker run命令將運(yùn)行失敗
十三仓技、ONBUILD
用于在Dockerfile中定義一個(gè)觸發(fā)器
Dockerfile用于build映像文件,此映像文件亦可作為base image被另一個(gè)Dockerfile用作FROM指令的參數(shù)俗他,并以之構(gòu)建新的映像文件
在后的這個(gè)Dockerfile中的FROM指令在build過(guò)程中被執(zhí)行時(shí)脖捻,將會(huì)“觸發(fā)”創(chuàng)建其base image的Dockerfile文件中的ONBUILD指令定義的觸發(fā)器
Syntax:
ONBUILD <INSTRUCTION>
注意:
盡管任何指令都可注冊(cè)成為觸發(fā)器指令,但ONBUILD不能自我嵌套兆衅,且不會(huì)觸發(fā)FROM和MAINTAINER指令
使用包含ONBUILD指令的Dockerfile構(gòu)建的鏡像應(yīng)該使用特殊的標(biāo)簽地沮,例如ruby:2.0-onbuild
在ONBUILD指令中使用ADD或COPY指令應(yīng)該格外小心嗜浮,因?yàn)樾聵?gòu)建過(guò)程和上下文在缺少指定的源文件時(shí)會(huì)失敗。
十四摩疑、HEALTHCHECK
Docker 1.12版本后引入的判斷容器狀態(tài)是否正常
Syntax:
HEALTHCHECK [OPTION] CMD <command> //設(shè)置檢查容器健康狀況的命令
HEALTHCHECK NONE //如果基礎(chǔ)鏡像有健康檢查指令危融,使用這行可屏蔽掉其健康檢查指令
在沒(méi)HEALTHCHECK指令前,Docker只能通過(guò)容器內(nèi)主進(jìn)程是否退出來(lái)判斷容器是否狀態(tài)異常雷袋。很多情況下這沒(méi)問(wèn)題吉殃,但是如果程序進(jìn)入死鎖狀態(tài),或者死循環(huán)狀態(tài)楷怒,應(yīng)用進(jìn)程并不退出蛋勺,但是該容器已經(jīng)無(wú)法提供服務(wù)了。雖然后端的程序可以通過(guò)前端的檢測(cè)工具來(lái)檢查狀態(tài)信息鸠删。但是最前端的服務(wù)就需要本身的檢測(cè)機(jī)制加上監(jiān)控抱完,就可以做到出現(xiàn)問(wèn)題解決問(wèn)題。
當(dāng)在一個(gè)鏡像指定了 HEALTHCHECK 指令后刃泡,用其啟動(dòng)容器巧娱,初始狀態(tài)會(huì)為 starting,在 HEALTHCHECK 指令檢查成功后變?yōu)?healthy烘贴,如果連續(xù)一定次數(shù)失敗禁添,則會(huì)變?yōu)?unhealthy。
HEALTHCHECK支持下列選項(xiàng):
- --interval=<間隔> : 兩次健康檢查間隔庙楚,默認(rèn)30秒
- --timeout=<時(shí)長(zhǎng)> : 健康檢查命令運(yùn)行超時(shí)時(shí)間上荡,如果超過(guò)這個(gè)時(shí)間,本次健康檢查就被視為失敗馒闷,默認(rèn)為30秒
- --retries=<次數(shù)> :當(dāng)連續(xù)失敗指定次數(shù)后酪捡,則將容器狀態(tài)視為unhealthy,默認(rèn)3次。
和CMD纳账、ENTRYPOINT一樣逛薇,HEALTHCHECK只可以出現(xiàn)一次,如果寫了多個(gè)疏虫,只有最后一個(gè)生效永罚。CMD 后面的命令也分為shell和exec格式。命令的返回值決定了該次檢查的成功與否: 0表示成功;1表示失敗;2保留卧秘。
ex:
HEALTHCHECK --interval=5s --timeout=3s \
CMD curl -fs http://localhost/ || exit 1
命令收集:
容器生命周期管理 — docker [run|start|stop|restart|kill|rm|pause|unpause]
容器操作運(yùn)維 — docker [ps|inspect|top|attach|exec|events|logs|wait|export|import|port]
容器rootfs命令 — docker [commit|cp|diff]
鏡像倉(cāng)庫(kù) — docker [login|pull|push|search]
本地鏡像管理 — docker [images|rmi|tag|build|history|save|import]
其他命令 — docker [info|version]
查看docker信息:
$ docker version
# 或者
$ docker info</pre>
Docker 需要用戶具有 sudo 權(quán)限呢袱,為了避免每次命令都輸入sudo
,可以把用戶加入 Docker 用戶組(官方文檔)
$ sudo usermod -aG docker $USER
服務(wù)啟動(dòng)翅敌,重啟羞福,狀態(tài)
[hongdada@localhost home]$ systemctl stop docker.service
[hongdada@localhost home]$ systemctl restart docker.service
[hongdada@localhost home]$ systemctl status docker.service</pre>
images相關(guān)命令:
以鏡像centos為例
登錄倉(cāng)庫(kù) docker login
查找鏡像docker search centos
下載鏡像docker pull centos
上傳鏡像docker push centos
刪除鏡像docker rmi centos 說(shuō)明:如果有多個(gè)tag,則指定tag只會(huì)刪除tag蚯涮,而不會(huì)刪除鏡像本身治专。
查看鏡像docker images
查看具體某一個(gè)鏡像的詳細(xì)信息:docker inspect centos
更改tag: docker tag docker.io/centos 21yunwei:latest
創(chuàng)建鏡像docker commit 容器ID 鏡像名稱 注:創(chuàng)建鏡像有三種方式卖陵,基于容器創(chuàng)建,基于本地模板創(chuàng)建张峰,基于dockerfile創(chuàng)建
保存鏡像docker save -o testcentos.tar 21yunwei:latest
載入鏡像docker load < tesetcentos.tar
# 列出本機(jī)的所有 image 文件泪蔫。
$ docker image ls
# 刪除 image 文件
$ docker image rm [imageName]
# 搜索鏡像
$ docker search mysql (輸出信息包括鏡像名字、描述喘批、星級(jí)撩荣、是否為官方創(chuàng)建、是否自動(dòng)創(chuàng)建)
# image 文件從倉(cāng)庫(kù)抓取到本地饶深。
$ docker image pull library/hello-world
# 運(yùn)行image文件
$ docker container run hello-world
container相關(guān)命令:
列出本機(jī)正在運(yùn)行的容器:docker container ls
列出本機(jī)所有容器婿滓,包括終止運(yùn)行的容器:docker container ls --all
創(chuàng)建容器docker create -ti image 容器ID:cid
啟動(dòng)容器docker start cid
運(yùn)行容器docker run -dit cid 等同于docker create+docker start
停止容器服務(wù) docker container kill cid
關(guān)閉容器docker stop cid
重啟容器docker restart cid
刪除容器docker rm cid #注意數(shù)據(jù)卷
刪除所有容器docker rm `docker ps -a -q` docker kill `docker ps -q`
阻塞對(duì)容器的其他調(diào)用方法,直到容器停止后退出 docker wait cid
查看容器docker ps 或者docker ps -a
列出容器ID docker ps -q (docker ps -q -a)
容器文件拷貝 docker cp cid:路徑 宿主機(jī)路徑或docker cp 宿主機(jī)路徑你 cid:路徑
查看容器進(jìn)程docker top cid
查看容器日志docker logs cid
查看容器變化 docker diff cid
進(jìn)入容器docker exec -ti cid /bin/bash或者 docker attach cid(不推薦粥喜,終端顯示相同,顯示不安全且容易卡组偃)
查看容器詳細(xì)信息 docker inspect cid 包括配置信息额湘,名稱,命令旁舰、網(wǎng)路配置以及很多有用數(shù)據(jù)
查看容器端口 docker port cid
導(dǎo)出容器docker export 3ad>21yunwei.tar
導(dǎo)入容器cat 21yunwei.tar | docker import -test/centos:latest
參考:
https://www.cnblogs.com/dance-walter/p/9581508.html
https://www.cnblogs.com/edisonchou/p/dockerfile_inside_introduction.html
https://www.cnblogs.com/hongdada/p/8906967.html
https://baijiahao.baidu.com/s?id=1641433332828402192&wfr=spider&for=pc