我們在理解 docker 之前,首先我們得先區(qū)分清楚兩個概念,容器和虛擬機。
可能很多讀者朋友都用過虛擬機,而對容器這個概念比較的陌生。
我們用的傳統(tǒng)虛擬機如 VMware , VisualBox 之類的需要模擬整臺機器包括硬件,每臺虛擬機都需要有自己的操作系統(tǒng),虛擬機一旦被開啟,預分配給它的資源將全部被占用。每一臺虛擬機包括應用,必要的二進制和庫,以及一個完整的用戶操作系統(tǒng)。
而容器技術是和我們的宿主機共享硬件資源及操作系統(tǒng),可以實現(xiàn)資源的動態(tài)分配。容器包含應用和其所有的依賴包,但是與其他容器共享內(nèi)核。容器在宿主機操作系統(tǒng)中,在用戶空間以分離的進程運行。
容器技術是實現(xiàn)操作系統(tǒng)虛擬化的一種途徑,可以讓您在資源受到隔離的進程中運行應用程序及其依賴關系。通過使用容器,我們可以輕松打包應用程序的代碼、配置和依賴關系,將其變成容易使用的構建塊,從而實現(xiàn)環(huán)境一致性、運營效率、開發(fā)人員生產(chǎn)力和版本控制等諸多目標。容器可以幫助保證應用程序快速、可靠、一致地部署,其間不受部署環(huán)境的影響。容器還賦予我們對資源更多的精細化控制能力,讓我們的基礎設施效率更高。通過下面這幅圖我們可以很直觀的反映出這兩者的區(qū)別所在。

Docker 屬于 Linux 容器的一種封裝,提供簡單易用的容器使用接口。它是目前最流行的 Linux 容器解決方案。
而 Linux 容器是 Linux 發(fā)展出了另一種虛擬化技術,簡單來講, Linux 容器不是模擬一個完整的操作系統(tǒng),而是對進程進行隔離,相當于是在正常進程的外面套了一個保護層。對于容器里面的進程來說,它接觸到的各種資源都是虛擬的,從而實現(xiàn)與底層系統(tǒng)的隔離。
Docker 將應用程序與該程序的依賴,打包在一個文件里面。運行這個文件,就會生成一個虛擬容器。程序在這個虛擬容器里運行,就好像在真實的物理機上運行一樣。有了 Docker ,就不用擔心環(huán)境問題。
總體來說, Docker 的接口相當簡單,用戶可以方便地創(chuàng)建和使用容器,把自己的應用放入容器。容器還可以進行版本管理、復制、分享、修改,就像管理普通的代碼一樣。
Docker的優(yōu)勢
Docker相比于傳統(tǒng)虛擬化方式具有更多的優(yōu)勢:
-
docker啟動快速屬于秒級別。虛擬機通常需要幾分鐘去啟動 -
docker需要的資源更少,docker在操作系統(tǒng)級別進行虛擬化,docker容器和內(nèi)核交互,幾乎沒有性能損耗,性能優(yōu)于通過Hypervisor層與內(nèi)核層的虛擬化 -
docker更輕量,docker的架構可以共用一個內(nèi)核與共享應用程序庫,所占內(nèi)存極小。同樣的硬件環(huán)境,Docker運行的鏡像數(shù)遠多于虛擬機數(shù)量,對系統(tǒng)的利用率非常高 - 與虛擬機相比,
docker隔離性更弱,docker屬于進程之間的隔離,虛擬機可實現(xiàn)系統(tǒng)級別隔離 - 安全性:
docker的安全性也更弱。Docker的租戶root和宿主機root等同,一旦容器內(nèi)的用戶從普通用戶權限提升為root權限,它就直接具備了宿主機的root權限,進而可進行無限制的操作。虛擬機租戶root權限和宿主機的root虛擬機權限是分離的,并且虛擬機利用如Intel的VT-d和VT-x的ring-1硬件隔離技術,這種隔離技術可以防止虛擬機突破和彼此交互,而容器至今還沒有任何形式的硬件隔離,這使得容器容易受到攻擊 - 可管理性:
docker的集中化管理工具還不算成熟。各種虛擬化技術都有成熟的管理工具,例如VMware vCenter提供完備的虛擬機管理能力 - 高可用和可恢復性:
docker對業(yè)務的高可用支持是通過快速重新部署實現(xiàn)的。虛擬化具備負載均衡,高可用,容錯,遷移和數(shù)據(jù)保護等經(jīng)過生產(chǎn)實踐檢驗的成熟保障機制,VMware可承諾虛擬機99.999%高可用,保證業(yè)務連續(xù)性 - 快速創(chuàng)建、刪除:虛擬化創(chuàng)建是分鐘級別的,
Docker容器創(chuàng)建是秒級別的,Docker的快速迭代性,決定了無論是開發(fā)、測試、部署都可以節(jié)約大量時間 - 交付、部署:虛擬機可以通過鏡像實現(xiàn)環(huán)境交付的一致性,但鏡像分發(fā)無法體系化。
Docker在Dockerfile中記錄了容器構建過程,可在集群中實現(xiàn)快速分發(fā)和快速部署
我們可以從下面這張表格很清楚地看到容器相比于傳統(tǒng)虛擬機的特性的優(yōu)勢所在:
| 特性 | 容器 | 虛擬機 |
|---|---|---|
| 啟動 | 秒級 | 分鐘級 |
| 硬盤使用 | 一般為MB | 一般為GB |
| 性能 | 接近原生 | 弱于 |
| 系統(tǒng)支持量 | 單機支持上千個容器 | 一般是幾十個 |
Docker的三個基本概念

從上圖我們可以看到,Docker 中包括三個基本的概念:
- Image(鏡像)
- Container(容器)
- Repository(倉庫)
鏡像是 Docker 運行容器的前提,倉庫是存放鏡像的場所,可見鏡像更是 Docker 的核心。
Image (鏡像)
那么鏡像到底是什么呢?
Docker 鏡像可以看作是一個特殊的文件系統(tǒng),除了提供容器運行時所需的程序、庫、資源、配置等文件外,還包含了一些為運行時準備的一些配置參數(shù)(如匿名卷、環(huán)境變量、用戶等)。鏡像不包含任何動態(tài)數(shù)據(jù),其內(nèi)容在構建之后也不會被改變。
鏡像(Image)就是一堆只讀層(read-only layer)的統(tǒng)一視角,也許這個定義有些難以理解,下面的這張圖能夠幫助讀者理解鏡像的定義。

從左邊我們看到了多個只讀層,它們重疊在一起。除了最下面一層,其它層都會有一個指針指向下一層。這些層是Docker 內(nèi)部的實現(xiàn)細節(jié),并且能夠在主機的文件系統(tǒng)上訪問到。統(tǒng)一文件系統(tǒng) (union file system) 技術能夠將不同的層整合成一個文件系統(tǒng),為這些層提供了一個統(tǒng)一的視角,這樣就隱藏了多層的存在,在用戶的角度看來,只存在一個文件系統(tǒng)。我們可以在圖片的右邊看到這個視角的形式。
Container (容器)
容器 (container) 的定義和鏡像 (image) 幾乎一模一樣,也是一堆層的統(tǒng)一視角,唯一區(qū)別在于容器的最上面那一層是可讀可寫的。

由于容器的定義并沒有提及是否要運行容器,所以實際上,容器 = 鏡像 + 讀寫層。
Repository (倉庫)
Docker 倉庫是集中存放鏡像文件的場所。鏡像構建完成后,可以很容易的在當前宿主上運行,但是, 如果需要在其它服務器上使用這個鏡像,我們就需要一個集中的存儲、分發(fā)鏡像的服務,Docker Registry (倉庫注冊服務器)就是這樣的服務。有時候會把倉庫 (Repository) 和倉庫注冊服務器 (Registry) 混為一談,并不嚴格區(qū)分。Docker 倉庫的概念跟 Git 類似,注冊服務器可以理解為 GitHub 這樣的托管服務。實際上,一個 Docker Registry 中可以包含多個倉庫 (Repository) ,每個倉庫可以包含多個標簽 (Tag),每個標簽對應著一個鏡像。所以說,鏡像倉庫是 Docker 用來集中存放鏡像文件的地方類似于我們之前常用的代碼倉庫。
通常,一個倉庫會包含同一個軟件不同版本的鏡像,而標簽就常用于對應該軟件的各個版本 。我們可以通過<倉庫名>:<標簽>的格式來指定具體是這個軟件哪個版本的鏡像。如果不給出標簽,將以 latest 作為默認標簽.。
倉庫又可以分為兩種形式:
-
public(公有倉庫) -
private(私有倉庫)
Docker Registry 公有倉庫是開放給用戶使用、允許用戶管理鏡像的 Registry 服務。一般這類公開服務允許用戶免費上傳、下載公開的鏡像,并可能提供收費服務供用戶管理私有鏡像。
除了使用公開服務外,用戶還可以在本地搭建私有 Docker Registry 。Docker 官方提供了 Docker Registry鏡像,可以直接使用做為私有 Registry 服務。當用戶創(chuàng)建了自己的鏡像之后就可以使用 push 命令將它上傳到公有或者私有倉庫,這樣下次在另外一臺機器上使用這個鏡像時候,只需要從倉庫上 pull 下來就可以了。
我們主要把 Docker 的一些常見概念如 Image , Container , Repository 做了詳細的闡述,也從傳統(tǒng)虛擬化方式的角度闡述了 docker 的優(yōu)勢,我們從下圖可以直觀地看到 Docker 的架構:

Docker 使用 C/S 結構,即客戶端/服務器體系結構。 Docker 客戶端與 Docker 服務器進行交互,Docker服務端負責構建、運行和分發(fā) Docker 鏡像。 Docker 客戶端和服務端可以運行在一臺機器上,也可以通過 RESTful 、 stock 或網(wǎng)絡接口與遠程 Docker 服務端進行通信。

這張圖展示了 Docker 客戶端、服務端和 Docker 倉庫(即 Docker Hub 和 Docker Cloud ),默認情況下Docker 會在 Docker 中央倉庫尋找鏡像文件,這種利用倉庫管理鏡像的設計理念類似于 Git ,當然這個倉庫是可以通過修改配置來指定的,甚至我們可以創(chuàng)建我們自己的私有倉庫。
Docker的安裝
Docker Platform
- Docker提供了一個開發(fā)、打包、運行app的平臺
-
Docker把app和底層infrastructure隔離開來
image.png
Docker Engine
Docker Engine是一個C/S架構的應用程序,主要包含下面幾個組件;
- 常駐后臺進程Dockerd
- 一個用來和Dockerd交互的REST API Server
-
命令行CLI接口,通過和REST API進行交互
image.png
Docker架構

Docker 的核心組件包括:
- Docker Client
- Docker daemon
- Docker Image
- Docker Registry
- Docker Container
Docker Damon
Docker Damon來監(jiān)聽Docker API的請求和管理Docker對象,比如鏡像、容器、網(wǎng)絡和Volume。
Docker Client
docker client是我們和Docker進行交互的最主要的方式方法,比如可以通過docker run來運行一個容器,然后我們的這個client會把命令發(fā)送給上面的Docker。
Docker Registry
Docker Registry 用來存儲Docker鏡像的倉庫,Docker Hub是Docker官方提供的一個公共倉庫,而且Docker默認也是從Docker Hub上查找鏡像的,當然你也可以很方便的運行一個私有倉庫,當我們使用docker pull或者docker run命令時,就會從我們配置的Docker鏡像倉庫中去拉取鏡像,使用docker push命令時,會將我們構建的鏡像推送到對應的鏡像倉庫中。
Images 鏡像
鏡像是一個制度模板,帶有Docker容器的說明。一般來說的,鏡像會基于另外的一些基礎鏡像上面安裝一個Nginx服務器,這樣就可以構建一個屬于我們自己的鏡像了。
Containers 容器
容器是一個鏡像的可運行的實例,可以使用Docker REST API或者CLI來操作容器,容器的實質是進程,但與直接在宿主執(zhí)行的實例進程不同,容器進程屬于自己的獨立的命名空間。因此容器可以擁有自己的root文件系統(tǒng)、自己的網(wǎng)絡配置、自己的進程空間、甚至自己的用戶ID。容器內(nèi)的經(jīng)常是運行在一個隔離的環(huán)境里,使用起來,就好像在一個獨立于宿主的系統(tǒng)下操作一樣。這種特性使得容器封裝的應用比直接在宿主運行更加安全。
Docker底層的技術支持
Namespaces:做隔離pid、net、ipc、mnt、uts
Control groups:做資源限制
Union file systems:Container和image的分層
Docker Image概述
- 文件和meta data的集合(root filesystem)
- 分層的,并且每一層都可以添加、改變和刪除文件,成為一個新的image
- 不同的image可以共享相同的layer
-
Image本身是read-only的
Docker技術里最為基礎的兩大概念:鏡像和容器。
鏡像的獲取方式:
- 從registry拉取
- 從Dockerfile構建
搜索鏡像
docker search <image> # 在docker index中搜索image
--automated=false 僅顯示自動創(chuàng)建的鏡像
--no-trunc=false 輸出信息不截斷顯示
-s 0 指定僅顯示評價為指定星級的鏡像
下載鏡像
docker pull <image> # 從docker registry server 中下拉image
還可通過指定標簽下載某鏡像
docker pull [:TAG]
docker pull centos:7
查看鏡像/刪除
docker images: # 列出images
docker images -a # 列出所有的images(包含歷史)
docker ps -a #列出本機所有容器
docker rmi <image ID>: # 刪除一個或多個image
存出和載入鏡像
存出本地鏡像文件為.tar
docker save -o ubuntu_14.04.tar ubuntu:14.04
導入鏡像到本地鏡像庫
docker load --input ubuntu_14.04.tar或者
docker load < ubuntu_14.04.tar
上傳鏡像
用戶在dockerhub網(wǎng)站注冊后,即可上傳自制的鏡像。
docker push NAME[:TAG]
Container容器
- 通過Image創(chuàng)建(copy)
- 在Image layer之上建立一個container layer(可讀寫)
- 類比Java面向對象:類和實例
-
Image負責app的存儲和分發(fā),Container負責運行app
image.png
創(chuàng)建(使用鏡像創(chuàng)建容器):
首先得查看鏡像的REPOSITORY和TAG
docker run -i -t REPOSITORY:TAG (等價于先執(zhí)行docker create 再執(zhí)行docker start 命令)
其中-t選項讓docker分配一個偽終端并綁定到容器的標準輸入上, -i則讓容器的標準輸入保持打開。若要在后臺以守護態(tài)(daemonized)形式運行,可加參數(shù)-d
在執(zhí)行docker run來創(chuàng)建并啟動容器時,后臺運行的標準包括:
- 檢查本地是否存在指定的鏡像,不存在就從公有倉庫下載
- 利用鏡像創(chuàng)建并啟動一個容器
- 分配一個文件系統(tǒng),并在只讀的鏡像層外面掛載一層可讀可寫層
- 從宿主機配置的網(wǎng)橋接口中橋接一個虛擬接口到容器
- 從地址池配置一個ip地址給容器
- 執(zhí)行用戶指定的應用程序
- 執(zhí)行完畢后容器被終止
docker start/stop/restart <container> #:開啟/停止/重啟container
進入容器:
docker attach [container_id] #連接一個正在運行的container實例(即實例須為start狀態(tài),可以多個 窗口同時attach 一個container實例),但當某個窗口因命令阻塞時,其它窗口也無法執(zhí)行了。
exec可直接在容器內(nèi)運行的命令。docker exec -ti [container_id] /bin/bash
刪除容器:
docker rm <container...> #:刪除一個或多個container
docker rm `docker ps -a -q` #:刪除所有的container
docker ps -a -q | xargs docker rm #:同上, 刪除所有的container
docker -rm
-f 強制中止并運行的容器
-l 刪除容器的連接,但保留容器
-v 刪除容器掛載的數(shù)據(jù)卷
修改容器:
docker commit <container> [repo:tag] # 將一個container固化為一個新的image,后面的repo:tag可選。
導入和導出容器:
導出到一個文件,不管是否處于運行狀態(tài)。
docker export CONTAINER > test.tar
導入為鏡像:
cat test.tar | docker import - centos:latest
Dockerfile語法梳理及最佳實踐
一、 FROM
Syntax:
FROM <image>[:<tag> | @<digest>] [AS <name>]
FROM指定一個基礎鏡像,且必須為Dockerfile文件開篇的每個非注釋行,至于image則可以是任何合理存在的image鏡像
FROM可以在一個Dockerfile中出現(xiàn)多次,以便于創(chuàng)建混合的images。如果沒有指定tag,latest將會被指定為要使用的基礎鏡像版本。
AS name,可以給新的構建階段賦予名稱。該名稱可用于后續(xù)FROM 和 COPY --from=<name | index>說明可以引用此階段中構建的鏡像

- 為了安全,盡量使用官方的image作為base image
二、LABEL
為鏡像生成元數(shù)據(jù)標簽信息
Syntax:
LABEL <KEY>=<VALUE> \
<KEY>="XXXX"
多個標簽寫成一行,避免在鏡像中額外增加layer

三、MAINTAINER
作者信息,寫在FROM后
Syntax:
MAINTAINER "auth <email>"
四、COPY
當復制一個目錄時,并不會復制目錄本身,而是會遞歸復制其下子目錄 至目標目錄下

Syntax:
COPY data /data/
文件復制準則
- <src>必須是build上下言文中的路徑,不能是其父目錄中的文件
- 如果<src>是目錄,則其內(nèi)部文件或子目錄會被遞歸復制,但<src>目錄自身不會被復制
- 如果指定了多個<src>,或在<src>中使用了通配符,則<dest>必須是一個目錄,且必須以/結尾
- 如果<dest>事先不存在,它將會被自動創(chuàng)建,這包括其父目錄路徑。
五、ADD
ADD指令類似于COPY指令,ADD支持使用TAR文件和URL路徑

Syntax:
ADD <src>...<dest>
ADD ["<src>",..."<dest>"]
操作準則:
- 如果<src>為URL且<dest>不以/結尾,則<src>指定的文件將被下載并直接被創(chuàng)建為<dest>;如果<dest>以/結尾,則文件名URL指定的文件將被直接下載并保存為<dest>/<filename>
- 如果<src>是一個本地文件系統(tǒng)上的壓縮格式的tar文件,它將被展開為一個目錄,其行為類似于"tar -x"命令;然而,通過URL獲取到的tar文件將不會自動展開。
- 如果<src>有多個,或其間接或直接使用了通配符,則<dest>必須是一個以/結尾的目錄路徑;如果<dest>不以/結尾,則其被視作一個普通文件,<src>內(nèi)容將被直接寫入到<dest>
- 為了讓鏡像盡量小,最好不要使用 ADD 指令從遠程 URL 獲取包,而是使用 curl 和 wget。這樣你可以在文件提取完之后刪掉不再需要的文件來避免在鏡像中額外添加一層。
示例:
額外操作:
ADD http://example.com/1.tar.gz /apps/
RUN tar xf /apps/1.tar.gz -C /apps/ && \
/bin/sh -c /apps/***.sh
簡單操作:
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外還有額外解壓縮功能
添加遠程文件 / 目錄,請使用curl或者wget
六、WORKDIR
用于為Dockerfile中所有RUN、CMD、ENTRYPOINT、COPY和ADD指令設定工作目錄

注意:
- 用WORKDIR,不要用RUN cd
- 盡量使用絕對目錄
Syntax:
WORKDIR <dirpath>
在Dockerfile文件中,WORKDIR指令可以出現(xiàn)多次,其路徑也可以為相對路徑,不過,其是相對此前一個WORKDIR指令指定的路徑
另外,WORKDIR也可調用由ENV指定定義的變量
ex:
WORKDIR /var/log
WORKDIR $STATEPATH
七、RUN
接受命令作為參數(shù)并用于創(chuàng)建鏡像,在之前的commit層上形成新的層。

注意:
- 為了美觀,復雜的RUN請用反斜線換行
- 避免無用分層,合并多條命令成一行
Syntax:
RUN \<command\>(如同執(zhí)行shell命令 /bin/sh -c)
RUN ["executable","param1","param2"]
- RUN 指令將在當前image中執(zhí)行任意合法命令并提交執(zhí)行結果。命令執(zhí)行提交后,就會自動執(zhí)行Dockerfile中的下一個指令。
- 分層RUN指令和生成提交符合Docker的核心概念,其中提交很輕量,可以從image將用于Dockerfile中的下一步。
- exec形式使得可以避免shell字符串變化,以及使用不包含指定的shell可執(zhí)行文件的基本image來運行RUN命令。
- 在shell形式中,可以使用\(反斜杠)將單個RUN指令繼續(xù)到下一行。例如:
RUN yum install -y \ openssl \ pcre-devel \ zlib
- 第二種語法格式中的參數(shù)是一個JSON格式的數(shù)組,其中<executable>為要運行的命令,后面的<paramN>為傳遞給命令的選項或對數(shù);然而,此種格式指定的命令不會以"/bin/sh -c"來發(fā)起,因此常見的shell操作如變量替換以及通配符(?,*等)替換將不會進行;不過,如果要運行的命令依賴于此shell特性的話,可以將其替換為類似下面的格式。
RUN ["/bin/bash","-c","<executable>","<param1>"]
RUN 指令的緩存在下一次構建期間不會自動失效。用于諸如:yum repolist 之類的指令的緩存將在下一次構建期間被重用。可以通過--no-cache 參數(shù)來使RUN指令的緩存無效,例如: docker build --no-cache
管理命令
某些RUN 命令依賴于使用管道字符( | )將管道輸出到另一個命令功能
RUN wget -O - http://www.baidu.com/index.html | wc -l > /app/html/baidu.html
Docker使用 /bin/sh -c 解釋執(zhí)行這些命令,解釋器只評估管道中最后一個操作的退出代碼以確定成功。在上面的例子中,只要wc -l 命令成功,即使wget 命令失敗,該構建步驟也會成功并生成新的鏡像。
由于管道中任何階段的錯誤而導致命令失敗,請預先 set -o pipefail && 確保意外錯誤可防止構建無意中成功。例如:
set -o pipefail : 表示在管道連接的命令序列中,只要有任何一個命令返回非0值,則整個管道返回非0值,即使最后一個命令返回0.
RUN set -o pipefail && wget -O - http://www.baidu.com/index.html | wc -l > /app/html/baidu.html
注意:
并非所有的shell都支持 -o pipefail 選項。在這種情況下(例如 dash shell,這是基于Debian的映像上的默認shell),請考慮使用exec形式RUN來明確選擇一個支持該pipefail選項的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指令也可用于運行任何命令或應用程序,不過,二者的運行時間點不同
- RUN 指令運行于映像文件構建過程中,而CMD指令運行于基于Dockerfile構建出的新鏡像文件啟動一個容器時。
- CMD指令的首要目的在于為啟動的容器指定默認要運行的程序,且其運行結束后,容器也將終止;不過,CMD指定的命令其可以被docker run的命令行選項所覆蓋
- 在Dockerfile中可以存在多個CMD指令,但僅最后一個生效
Syntax:
CMD <command> //支持命令展開,但是不支持傳遞信號
CMD ["<executable>","<param1>","<param2>"] //相當于容器的第一個命令,可以接受信號
CMD ["param1","param2"]
前兩種語法格式的意義同RUN
第三種則用于為ENTRYPOINT指令提供默認參數(shù)
CMD會在啟動容器的時候執(zhí)行,build時不執(zhí)行,而RUN只是在構建鏡像的時候執(zhí)行,后續(xù)鏡像構建完成之后,啟動容器就與RUN無關了。這個命令就相當于在/etc/rc.d/rc.local中寫命令
九、ENTRYPOINT
類似CMD指令的功能,用于為容器指定默認運行程序,從而使得容器像是一具單獨的可執(zhí)行程序
與CMD不同的是,由ENTRYPOINT啟動的程序不會被docker run命令行指定的參數(shù)所覆蓋,而且,這些命令行參數(shù)會被當作參數(shù)傳遞給ENTRYPOINT指定的程序。不過,docker run 命令的--entrypoint 選項的參數(shù)可覆蓋ENTRYPOINT指令指定的程序
Syntax:
ENTRYPOINT <command> //這種方式能接受shell命令行展開
ENTRYPOINT ["<executable>","param1"] //展開不了,但能接收到信號
docker run命令傳入的命令參數(shù)會覆蓋CMD指令的內(nèi)容并且附加到ENTRYPOINT命令最后做為其參數(shù)使用。Dockerfile文件中也可以存在多個ENTRYPOINT指令,但僅有最后一個會生效

十、EXPOSE
用來指定端口,使容器內(nèi)的應用可以通過端口和外界交互。
Syntax:
EXPOSE <port> [<port>...]
告訴Docker服務端容器對外映射的本地端口,需要在docker run 的時候使用-p 或者 -P 選項生效。
EXPOSE 80/tcp
十一、ENV
ENV指令可以用于docker容器設置環(huán)境變量
Syntax:
ENV <key> <value>
ENV <key>=<value> ...
指定一個環(huán)境變量,會被后續(xù)RUN指令使用,并在容器運行時保留。
ENV設置的環(huán)境變量,可以使用 docker inspect 命令來查看。同時還可以使用 docker run --env <key>=<value>來修改環(huán)境變量
盡量使用ENV增加可維護性

十二、USER
用于指定運行image時的或運行Dockerfile中任何RUN、CMD或ENTRYPOINT指令指定的程序時的用戶名或UID
默認情況下,container的運行身份為root用戶
Syntax:
USER <UID>|<UserName>
需要注意的是,<UID>可以為任意數(shù)字,但實踐中其必須為/etc/passwd中某用戶的有效UID,否則,docker run命令將運行失敗
十三、ONBUILD
用于在Dockerfile中定義一個觸發(fā)器
Dockerfile用于build映像文件,此映像文件亦可作為base image被另一個Dockerfile用作FROM指令的參數(shù),并以之構建新的映像文件
在后的這個Dockerfile中的FROM指令在build過程中被執(zhí)行時,將會“觸發(fā)”創(chuàng)建其base image的Dockerfile文件中的ONBUILD指令定義的觸發(fā)器
Syntax:
ONBUILD <INSTRUCTION>
注意:
盡管任何指令都可注冊成為觸發(fā)器指令,但ONBUILD不能自我嵌套,且不會觸發(fā)FROM和MAINTAINER指令
使用包含ONBUILD指令的Dockerfile構建的鏡像應該使用特殊的標簽,例如ruby:2.0-onbuild
在ONBUILD指令中使用ADD或COPY指令應該格外小心,因為新構建過程和上下文在缺少指定的源文件時會失敗。
十四、HEALTHCHECK
Docker 1.12版本后引入的判斷容器狀態(tài)是否正常
Syntax:
HEALTHCHECK [OPTION] CMD <command> //設置檢查容器健康狀況的命令
HEALTHCHECK NONE //如果基礎鏡像有健康檢查指令,使用這行可屏蔽掉其健康檢查指令
在沒HEALTHCHECK指令前,Docker只能通過容器內(nèi)主進程是否退出來判斷容器是否狀態(tài)異常。很多情況下這沒問題,但是如果程序進入死鎖狀態(tài),或者死循環(huán)狀態(tài),應用進程并不退出,但是該容器已經(jīng)無法提供服務了。雖然后端的程序可以通過前端的檢測工具來檢查狀態(tài)信息。但是最前端的服務就需要本身的檢測機制加上監(jiān)控,就可以做到出現(xiàn)問題解決問題。
當在一個鏡像指定了 HEALTHCHECK 指令后,用其啟動容器,初始狀態(tài)會為 starting,在 HEALTHCHECK 指令檢查成功后變?yōu)?healthy,如果連續(xù)一定次數(shù)失敗,則會變?yōu)?unhealthy。
HEALTHCHECK支持下列選項:
- --interval=<間隔> : 兩次健康檢查間隔,默認30秒
- --timeout=<時長> : 健康檢查命令運行超時時間,如果超過這個時間,本次健康檢查就被視為失敗,默認為30秒
- --retries=<次數(shù)> :當連續(xù)失敗指定次數(shù)后,則將容器狀態(tài)視為unhealthy,默認3次。
和CMD、ENTRYPOINT一樣,HEALTHCHECK只可以出現(xiàn)一次,如果寫了多個,只有最后一個生效。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]
容器操作運維 — docker [ps|inspect|top|attach|exec|events|logs|wait|export|import|port]
容器rootfs命令 — docker [commit|cp|diff]
鏡像倉庫 — docker [login|pull|push|search]
本地鏡像管理 — docker [images|rmi|tag|build|history|save|import]
其他命令 — docker [info|version]
查看docker信息:
$ docker version
# 或者
$ docker info</pre>
Docker 需要用戶具有 sudo 權限,為了避免每次命令都輸入sudo,可以把用戶加入 Docker 用戶組(官方文檔)
$ sudo usermod -aG docker $USER
服務啟動,重啟,狀態(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相關命令:
以鏡像centos為例
登錄倉庫 docker login
查找鏡像docker search centos
下載鏡像docker pull centos
上傳鏡像docker push centos
刪除鏡像docker rmi centos 說明:如果有多個tag,則指定tag只會刪除tag,而不會刪除鏡像本身。
查看鏡像docker images
查看具體某一個鏡像的詳細信息: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
# 列出本機的所有 image 文件。
$ docker image ls
# 刪除 image 文件
$ docker image rm [imageName]
# 搜索鏡像
$ docker search mysql (輸出信息包括鏡像名字、描述、星級、是否為官方創(chuàng)建、是否自動創(chuàng)建)
# image 文件從倉庫抓取到本地。
$ docker image pull library/hello-world
# 運行image文件
$ docker container run hello-world
container相關命令:
列出本機正在運行的容器:docker container ls
列出本機所有容器,包括終止運行的容器:docker container ls --all
創(chuàng)建容器docker create -ti image 容器ID:cid
啟動容器docker start cid
運行容器docker run -dit cid 等同于docker create+docker start
停止容器服務 docker container kill cid
關閉容器docker stop cid
重啟容器docker restart cid
刪除容器docker rm cid #注意數(shù)據(jù)卷
刪除所有容器docker rm `docker ps -a -q` docker kill `docker ps -q`
阻塞對容器的其他調用方法,直到容器停止后退出 docker wait cid
查看容器docker ps 或者docker ps -a
列出容器ID docker ps -q (docker ps -q -a)
容器文件拷貝 docker cp cid:路徑 宿主機路徑或docker cp 宿主機路徑你 cid:路徑
查看容器進程docker top cid
查看容器日志docker logs cid
查看容器變化 docker diff cid
進入容器docker exec -ti cid /bin/bash或者 docker attach cid(不推薦,終端顯示相同,顯示不安全且容易卡住)
查看容器詳細信息 docker inspect cid 包括配置信息,名稱,命令、網(wǎng)路配置以及很多有用數(shù)據(jù)
查看容器端口 docker port cid
導出容器docker export 3ad>21yunwei.tar
導入容器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



