本篇內(nèi)容介紹了“Dockerfile定制鏡像的方法”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
目前創(chuàng)新互聯(lián)已為千余家的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)頁空間、網(wǎng)站運(yùn)營(yíng)、企業(yè)網(wǎng)站設(shè)計(jì)、鄞州網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。
鏡像的定制實(shí)際上就是定制每一層所添加的配置、文件。我們可以把每一層修改、安裝、構(gòu)建、操作的命令都寫入一個(gè)腳本,這個(gè)腳本就是Dockerfile;
Dockerfile是一個(gè)文本文件,其內(nèi)包含了一條條的指令,每一條指令構(gòu)建一層,因此每一條指令的內(nèi)容,就是描述該層應(yīng)當(dāng)如何構(gòu)建;
FROM指定基礎(chǔ)鏡像
所謂定制鏡像,一定是以一個(gè)鏡像為基礎(chǔ),在其上進(jìn)行定制?;A(chǔ)鏡像是必須指定的,而FROM就是指定基礎(chǔ)鏡像,因此一個(gè)Dockerfile中FROM是必備的指令,并且必須是第一條指令;
在docker hub上有非常多的高質(zhì)量的官方鏡像,有可以直接拿來使用的服務(wù)類鏡像,如nginx、redis、MySQL、tomcat等;可以在其中尋找一個(gè)最符合我們最終目標(biāo)的鏡像為基礎(chǔ)鏡像進(jìn)行定制;
如果沒有找到對(duì)應(yīng)服務(wù)的鏡像,官方鏡像中還提供了一些更為基礎(chǔ)的操作系統(tǒng)鏡像,如ubuntu、debian、centos、alpine等,這些操作系統(tǒng)的軟件庫為我們提供了更廣闊的擴(kuò)展空間;
除了選擇現(xiàn)有鏡像為基礎(chǔ)鏡像外,Docker還存在一個(gè)特殊的鏡像,名為scratch。這個(gè)鏡像是一個(gè)虛擬的概念,并不實(shí)際存在,它表示一個(gè)空白的鏡像;
FROM scratch
如果你以scratch為基礎(chǔ)鏡像的話,意味著你不以任何鏡像為基礎(chǔ),接下來所寫的指令將作為鏡像的第一層開始存在。
對(duì)于Linux下靜態(tài)編譯的程序來說,并不需要有操作系統(tǒng)提供運(yùn)行時(shí)支持,所需的一切庫都已經(jīng)在可執(zhí)行文件里了,因此直接FROM scratch
會(huì)讓鏡像體積更加小巧。使用Go語言開發(fā)的應(yīng)用很多會(huì)使用這種方式來制作鏡像,這也是為什么有人認(rèn)為Go是特別適合容器微服務(wù)架構(gòu)的語言的原因之一。
RUN執(zhí)行命令
RUN指令是用來執(zhí)行命令行命令的。由于命令行的強(qiáng)大能力,RUN指令在定制鏡像時(shí)是最常用的指令之一。其格式有兩種:
// shell格式 RUN <命令>
// 示例 RUN echo '<h2>Hello, Docker!</h2>' /usr/share/nginx/html/index.html
// exec格式 RUN ["可執(zhí)行文件", "參數(shù)1", "參數(shù)2"]
// 示例 RUN tar -zxf redis.tar.gz -C /usr/src/redis --strip-components=1 RUN make -C /usr/src/redis RUN make -C /usr/src/redis install
構(gòu)建鏡像
上面我們利用Dockerfile定制了nginx鏡像,現(xiàn)在我們明白了Dockerfile的內(nèi)容,接下來我們來構(gòu)建這個(gè)鏡像。在Dockerfile文件所在目錄執(zhí)行:
docker build -t nginx:v3 . // 注意最后有一個(gè).表示當(dāng)前目錄
從命令的輸出結(jié)果中,我們可以清晰的看到鏡像的構(gòu)建過程。在step 2中,RUN指令啟動(dòng)了一個(gè)容器,執(zhí)行了所要求的命令,并最后將該容器進(jìn)行了提交,隨后刪除了所用到的這個(gè)容器。
COPY復(fù)制文件
格式
COPY <源路徑>...<目標(biāo)路徑>
COPY ["<源路徑1>",..."[目標(biāo)路徑]"]
COPY指令將從構(gòu)建上下文目錄中<源路徑>的文件/目錄復(fù)制到新的一層的鏡像內(nèi)的<目標(biāo)路徑>位置。比如:
COPY package.json /usr/src/app/
<源路徑>可以是多個(gè),甚至可以是通配符,如:
COPY hom* /mydir/ COPY hom?.txt /mydir/
ADD更高級(jí)的復(fù)制文件
ADD指令和COPY的格式和性質(zhì)基本一致。但是在COPY基礎(chǔ)上增加了一些功,比如<源路徑>可以是一個(gè)URL,這種情況下,Docker引擎會(huì)試圖去下載這個(gè)鏈接的文件放到<目標(biāo)路徑>去。
在Docker官方的Dockerfile最佳實(shí)踐文檔中要求,盡可能的使用COPY,因?yàn)镃OPY的語義很明確,就是復(fù)制文件而已,而ADD則包含了更復(fù)雜的功能,其行為也不一定很清晰。最適合使用ADD的場(chǎng)合,就是所提及的需要自動(dòng)解壓縮的場(chǎng)合。因此在COPY和ADD指令中選擇的時(shí)候,可以遵循這樣的原則,所有的文件復(fù)制均使用COPY指令,僅在需要自動(dòng)解壓縮的場(chǎng)合使用ADD。
CMD容器啟動(dòng)命令
shell格式:CMD <命令>
;
exec格式:CMD ["可執(zhí)行文件", "參數(shù)1", "參數(shù)2",...]
;
參數(shù)列表格式:CMD ["參數(shù)1", "參數(shù)2",...]
。在指定了ENTRYPOINT
指令后,用CMD指定具體的參數(shù);
CMD命令的格式和RUN相似,也是兩種格式:
docker不是虛擬機(jī),容器就是進(jìn)程。既然是進(jìn)程,那么在啟動(dòng)容器的時(shí)候,需要指定所運(yùn)行的程序及參數(shù)。CMD指令就是用于指定默認(rèn)的容器主進(jìn)程啟動(dòng)命令的。
ENTRYPOINT入口點(diǎn)
ENTRYPOINT的目的和CMD一樣,都是在指定容器啟動(dòng)程序及參數(shù)。ENTRYPOINT在運(yùn)行時(shí)也可以替代,不過比CMD要略顯繁瑣,需要通過docker run
的參數(shù)--entrypoint
來指定。當(dāng)指定了ENTRYPOINT之后,CMD的含義就發(fā)生了改變,不再是直接的運(yùn)行其命令,而是將CMD的內(nèi)容作為參數(shù)傳給ENTRYPOINT指令,換句話說,實(shí)際執(zhí)行命令時(shí),將變?yōu)椋?/p>
<ENTRYPOINT> "<CMD>"
ENV設(shè)置環(huán)境變量
ENV <key> <value>
;
ENV <key1>=<value1> <key2>=<value2>
;
格式有兩種:
這個(gè)指令很簡(jiǎn)單,就是設(shè)置環(huán)境變量而已,無論是后面的其他指令,如RUN,還是運(yùn)行時(shí)的應(yīng)用,都可以直接使用這里定義的環(huán)境變量;
ENV VERSION=1.0 DEBUG=ON NAME="Happy Feet" $VERSION # 使用環(huán)境變量
下列指令可以支持環(huán)境變量展開:ADD、COPY、ENV、EXPOSE、LABEL、USER、WORKDIR、VOLUME、STOPSIGNAL、ONBUILD。
ARG構(gòu)建參數(shù)
ARG <參數(shù)名>[=<默認(rèn)值>]
;
格式:
構(gòu)建參數(shù)和ENV的效果一樣,都是設(shè)置環(huán)境變量。所不同的是,ARG所設(shè)置的構(gòu)建環(huán)境變量,在將來容器運(yùn)行時(shí)是不會(huì)存在這些環(huán)境變量的。但是不要因此就使用ARG保存密碼之類的信息,因?yàn)閐ocker history還是可以看到所有值的;
Dockerfile中的ARG指令是定義參數(shù)名稱,以及定義其默認(rèn)值。該默認(rèn)值可以在構(gòu)建命令docker build
中使用--build-arg <參數(shù)名>=<參數(shù)值>
來覆蓋。
VOLUME定義匿名卷
格式:
VOLUME ["<路徑1>", "<路徑2>",...]
VOLUME <路徑>
容器運(yùn)行時(shí)應(yīng)盡量保持容器存儲(chǔ)層不發(fā)生寫操作,對(duì)于數(shù)據(jù)庫類需要保存動(dòng)態(tài)數(shù)據(jù)的應(yīng)用,其數(shù)據(jù)庫文件應(yīng)該保存于卷(volume)中,為了防止運(yùn)行時(shí)用戶忘記將動(dòng)態(tài)文件所保存目錄掛載為卷,在Dockerfile中,我們可以事先指定某些目錄掛載為匿名卷,這樣在運(yùn)行時(shí)如果用戶不指定掛載,其應(yīng)用也可以正常運(yùn)行,不會(huì)向容器存儲(chǔ)層寫入大量數(shù)據(jù)。
VOLUMEN /data
EXPOSE聲明端口
幫助鏡像使用者理解這個(gè)鏡像服務(wù)的守護(hù)端口,以方便配置映射;
在運(yùn)行時(shí)使隨機(jī)端口映射時(shí),也就是docker run -P
時(shí),會(huì)自動(dòng)隨機(jī)映射EXPOSE的端口。
格式為EXPOSE <端口1> [<端口2>,...]
;
EXPOSE指令是聲明運(yùn)行時(shí)容器提供服務(wù)端口,這只是一個(gè)聲明,在運(yùn)行時(shí)并不會(huì)因?yàn)檫@個(gè)聲明應(yīng)用就會(huì)開啟這個(gè)端口的服務(wù)。
在Dockerfile中使用EXPOSE進(jìn)行聲明有兩個(gè)好處:
WORKDIR指定工作目錄
在shell中,連續(xù)兩行是同一個(gè)進(jìn)程執(zhí)行環(huán)境,因此前一個(gè)命令修改的內(nèi)存狀態(tài),會(huì)直接影響后一個(gè)命令;
在Dockerfile中,這兩行RUN命令的執(zhí)行環(huán)境根本不同,是兩個(gè)完全不同的容器。這就是對(duì)Dockerfile構(gòu)建分層存儲(chǔ)的概念不了解所導(dǎo)致的錯(cuò)誤。每一個(gè)RUN都是啟動(dòng)一個(gè)容器、執(zhí)行命令、然后提交存儲(chǔ)層文件變更。第一層RUN cd /app
的執(zhí)行僅僅是當(dāng)前進(jìn)程的工作目錄變更,一個(gè)內(nèi)存上的變化而已,其結(jié)果不會(huì)造成任何文件變更。而到第二層的時(shí)候,啟動(dòng)的是一個(gè)全新的容器,跟第一層的容器更完全沒關(guān)系,自然不可能繼承前一層構(gòu)建過程中的內(nèi)存變化。
因此如果需要改變以后各層的工作目錄的位置,那么應(yīng)該使用WORKDIR指令。
格式為WORKDIR <工作目錄路徑>
;
使用WORKDIR指令可以來指定工作目錄(或者稱為當(dāng)前目錄),以后各層的當(dāng)前目錄就被改為指定的目錄,如果該目錄不存在,WORKDIR會(huì)幫你建立目錄;
之前提到一些初學(xué)者常犯的錯(cuò)誤是把Dockerfile等同于shell腳本來寫,這種錯(cuò)誤的理解還可能會(huì)導(dǎo)致出現(xiàn)下面這樣的錯(cuò)誤:
RUN cd /app RUN echo "hello" > world.txt
如果將這個(gè)Dockerfile進(jìn)行構(gòu)建鏡像運(yùn)行后,會(huì)發(fā)現(xiàn)找不到/app/world.txt文件。
USER指定當(dāng)前用戶
格式:USER <用戶名>
;
USER指令和WORKDIR相似,都是改變環(huán)境狀態(tài)并影響以后的層。WORKDIR是改變工作目錄,USER則是改變之后層的執(zhí)行RUN,CMD以及ENTRYPOINT這類命令的身份。
當(dāng)然,和WORKDIR一樣,USER只是幫助你切換到指定用戶而已,這個(gè)用戶必須是事先建立好的,否則無法切換
RUN groupadd -r redis && useradd -r -g redis redis USER redis RUN ["redis-server"]
HEALTHCHECK健康檢查
--interval=<間隔>
:兩次健康檢查的間隔,默認(rèn)為30秒;
--timeout=<時(shí)長(zhǎng)>
:健康檢查命令運(yùn)行超時(shí)時(shí)間,如果超過這個(gè)事件,本次健康檢查就被視為失敗,默認(rèn)為30秒;
--retries=<次數(shù)>
:當(dāng)連續(xù)失敗指定次數(shù)后,則將容器狀態(tài)視為unhealthy,默認(rèn)3次。
格式:
# 設(shè)置檢查容器健康狀況的命令 HEALTHCHECK [選項(xiàng)] CMD <命令> # 如果基礎(chǔ)鏡像有健康檢查指令,可以屏蔽掉其健康檢查指令 HEALTHCHECK NONE
HEALTHCHECK指令是告訴Docker應(yīng)該如何進(jìn)行判斷容器的狀態(tài)是否正常,這是Docker 1.12引入的新指令。通過該指令指定一行命令,用這行命令來判斷容器主進(jìn)程的服務(wù)狀態(tài)是否正常,從而比較真實(shí)的反應(yīng)容器實(shí)際狀態(tài)。
一個(gè)鏡像指定了HEALTHCHECK指令后,用其啟動(dòng)容器,初始狀態(tài)會(huì)為starting,在執(zhí)行健康檢查成功后變?yōu)閔ealthy,如果連續(xù)一定次數(shù)失敗,則會(huì)變?yōu)閡nhealthy;
HEALTHCHECK支持以下選項(xiàng):
為了幫助排障,健康檢查命令的輸出(包括stdout一級(jí)stderr)都會(huì)被保存于健康狀態(tài)里,可以通過docker inspect
來查看。
ONBUILD為他人做嫁衣
格式:ONBUILD <其他指令>
;
ONBUILD是一個(gè)特殊的指令,它后面跟的是其他指令,比如RUN,COPY等,而這些指令,在當(dāng)前鏡像構(gòu)建時(shí)并不會(huì)被執(zhí)行,只有當(dāng)以當(dāng)前鏡像為基礎(chǔ)鏡像,去構(gòu)建下一級(jí)鏡像的時(shí)候才會(huì)被執(zhí)行;
Dockerfile中的其他指令都是為了定制當(dāng)前鏡像而準(zhǔn)備的,唯有ONBUILD是為了幫助別人定制自己而準(zhǔn)備的。
docker save和docker load
Docker還提供了docker save
和docker load
命令,用以將鏡像保存為一個(gè)tar文件,然后傳輸?shù)搅硪粋€(gè)位置上,再加載進(jìn)來。這是沒有Docker Registry時(shí)的做法,現(xiàn)在已經(jīng)不推薦使用,鏡像遷移應(yīng)該直接使用Docker Registry,無論是直接使用Docker Hub還是使用內(nèi)網(wǎng)私有Registry都可以。
例如:保存nginx鏡像:
docker save nginx |gzip > nginx-latest.tar.gz
然后我們將nginx-latest.tar.gz文件復(fù)制到另一個(gè)機(jī)器上,再次加載鏡像:
docker load -i nginx-latest.tar.gz
“Dockerfile定制鏡像的方法”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
分享題目:Dockerfile定制鏡像的方法
本文鏈接:http://chinadenli.net/article26/ppsdcg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站內(nèi)鏈、電子商務(wù)、網(wǎng)站設(shè)計(jì)公司、定制網(wǎng)站、微信小程序、外貿(mào)網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)