使用Dockerfile創(chuàng)建鏡像

在上面的內(nèi)容中介紹了如何使用docker commit的方法來構(gòu)建鏡像,相反推薦使用被稱為Dockerfile的定義文件和docker build命令來構(gòu)建鏡像凡简。Dockerfile使用基本的基于DSL語法的指令來構(gòu)建一個Docker鏡像筐眷,之后使用docker build命令基于該Dockerfile中的指令構(gòu)建一個新的鏡像武翎。

(一)第一個Dockerfile

現(xiàn)在來創(chuàng)建一個最簡單的Dockerfile文件樣例霹疫,先創(chuàng)建一個空的Dockerfile文件屠阻,在任意目錄下都行蛉加,在Dockerfile文件中填入以下內(nèi)容丁眼。

FROM alpine:3.14

//設(shè)置容器內(nèi)的數(shù)據(jù)卷

VOLUME ["/var/html"]

EXPOSE 80

該Dockerfile由一系列指令和參數(shù)組成卢厂,每條指令融柬,如FROM,都必須為大寫字母且后面跟隨一個參數(shù):FROM alpine:3.14锅纺,Dockerfile中的指令會按順序從上到下執(zhí)行,所以應(yīng)該根據(jù)需要合理安排指令的順序驱入。

使用build命令構(gòu)建鏡像的步驟如下 :

第一步:Docker從基礎(chǔ)鏡像運行一個容器。

第二步:執(zhí)行數(shù)據(jù)卷指令來創(chuàng)建一個數(shù)據(jù)卷宴凉。

第三步:設(shè)置訪問端口

—— 最后所有指令執(zhí)行完畢窘行。

每個Dockerfile的第一條指令都應(yīng)該是FROM,F(xiàn)ROM指令指定一個已經(jīng)存在的鏡像后續(xù)指令都將基于該鏡像進行劫窒,這個鏡像被稱為基礎(chǔ)鏡像(base iamge)。在上面的Dockerfile示例中散怖,我們指定了alpine:3.14作為鏡像的基礎(chǔ)鏡像偏灿,基于這個Dockerfile構(gòu)建的新鏡像將以alpine:3.14操作系統(tǒng)為基礎(chǔ)枚荣,在運行一個容器時,必須要指明是基于哪個基礎(chǔ)鏡像在進行構(gòu)建害碾。

接著是VOLUME指令,用于指定數(shù)據(jù)卷的設(shè)置。

最后設(shè)置EXPOSE指令剃袍,這條指令告訴Docker該容器內(nèi)的應(yīng)用程序?qū)褂萌萜鞯闹付ǘ丝冢@并不意味著可以自動訪問任意容器運行中服務(wù)的端口,這里指定的是80端口棵红。

(二)Dockerfile指令

本小節(jié)主要針對Dockerfile文件中使用到的指令進行介紹致板,介紹Dockerfiler文件中常用的指令素征,在Dockerfile文件中所有的指令都必須使用大寫。

1.FROM

FROM指令的格式如下:

FROM [--platform=<platform>] <image> [AS <name>]

OR

FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]

OR

FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]

FROM指令表示初始化一個新構(gòu)建并作為后續(xù)指令的基本映像今豆,所以一個有效的Dockerfile文件必須以FROM指令開始情组,為個鏡像也必須是一個有效鏡像,可以從一些公用庫中來獲取相應(yīng)的鏡像。

但ARG可以放在FROM指令前面印蓖,關(guān)于ARG和FROM如何交互將會在后面介紹堕汞。

FROM可以在單個Dockerfile中多出現(xiàn)投放,這樣可以創(chuàng)建多個映像蛤肌,或?qū)⒁粋€構(gòu)建階段用作另一個構(gòu)建階段的依賴庫向胡。

FROM指令可以支持由其上一個指令A(yù)RG指令聲明的變量,并傳遞給FROM指令使用。

ARG CODE_VERSION=latest

FROM base:${CODE_VERSION}

CMD /code/run-app

FROM extras:${CODE_VERSION}

CMD /code/run-extras

2.RUN

RUN指令有兩種運行方式:

#shell格式:

RUN <command>

#exec格式:

RUN ["executable", "param1", "param2"]

# 例如:

# RUN ["./test.php", "dev", "offline"] 等價于 RUN ./test.php dev offline

注意:Dockerfile的指令每執(zhí)行一次都會在docker上新建一層若专,所以過多無意義的層淮逻,會造成鏡像膨脹過大车胡。

如上瘩将,以 && 符號連接命令欲险,這樣執(zhí)行后,只會創(chuàng)建 1 層鏡像。

3.CMD

CMD指令用于指定一個容器啟動時所運行的命令蚯斯,這有點類似于RUN指令狈蚤,但RUN指令是指定鏡像被構(gòu)建時要運行的命令,而CMD是指容器啟動時所要運行的命令锭魔,CMD指令有三種形式搂抒。

#exec格式 CMD ["executable","param1","param2"]

# 該寫法是為 ENTRYPOINT 指令指定的程序提供默認參數(shù) CMD ["param1","param2"]

#shell格式 CMD command param1 param2

一般推薦使用第一種格式容客,執(zhí)行過程清晰明確寓辱。第三種格式其實在運行過程中也會轉(zhuǎn)換成第一種格式運行缭保,并且默認可執(zhí)行文件是sh。

CMD和使用docker run命令啟動容器時指定運行命令幾乎一致碴巾。

#如在Dockerfile文件中寫以下指令

CMD ["/bin/true"]

#上面這個CMD等同以下面的run指令

root@ubunhomhome/test# docker run -it nginx /bin/true

在Dockerfile中只能有一個CMD指令,即使如果有多個CMD指令倘要,也只有最后一個CMD才會生效缰趋。

CMD指令主要是為執(zhí)行中的容器提供默認值,這些默認值可以包含可執(zhí)行文件,也可以省略可執(zhí)行文件,在這種情況下捕犬,就必須指定一條ENTRYPOINT指令。

如果用戶在使用docker run指定參數(shù)時,則它們將會覆蓋Dockerfile文件中的CMD參數(shù)默認值啸澡。

4.LABEL

LABEL指令用來給鏡像添加一些元數(shù)據(jù)(metadata)上沐,以鍵值對的形式龄广,語法格式如下:

LABEL <key>=<value> <key>=<value> <key>=<value> ...

如果LABEL值中需要跨多行敲才,則需要加入反斜杠和引號。

一個鏡像可以有多個標簽,可以在一行上指定多個標簽番舆,有以下兩種方式可以實現(xiàn)呛讲。

5.EXPOSE

該指令用于聲明監(jiān)聽的端口號雷逆,在監(jiān)聽是可以指定是TCP還是UDP協(xié)議,默認值為TCP膀哲,其主要有以下作用:

幫助鏡像使用理解這個鏡像服務(wù)的守護端口往产,以方便配置映射。

在運行時使用隨時端口映射某宪,也就是docker run -P時仿村,會自動隨機映射EXPOSE的端口蔼囊。

EXPOSE指令實際上并未發(fā)布指定端口,它是將我們訪問時輸入的端口和運行容器之間做一種關(guān)聯(lián)或通信滔灶,具體發(fā)布哪些端口表箭,要在運行容器時發(fā)布實際端口,可以使用docker run中-p或-P來設(shè)置映射的端口號溪掀。

默認情況下一般如果我們未指定協(xié)議的話骚勘,那么都是使用TCP協(xié)議殉疼,當然也可以指定具體的協(xié)議,也可以同時指定TCP和UDP協(xié)議淤井。

EXPOSE 80/tcp

EXPOSE 80/udp

6.ENV

設(shè)置環(huán)境變量,定義了環(huán)境變量,這樣在后續(xù)的指令中,就可以使用這個環(huán)境變量。如果在環(huán)境變量引用過程中包含空格,那么需要使用到反斜杠。

其語法格式如下:

ENV <key> <value>

ENV <key1>=<value1> <key2>=<value2>...

ENV MY_NAME="John Doe"

ENV MY_DOG=Rex\ The\ Dog

ENV MY_CAT=fluffy

使用ENV設(shè)置的環(huán)境變量會保留下來,當容器運行時可以使用docker inspect查看值泪酱,并且可以使用docker run --env = 更改環(huán)境變量的值张弛。

如果僅僅是在構(gòu)建過程中需要環(huán)境變量,而在最終映像中不需要想邦,可以考慮為單個命令設(shè)置一個值或使用ARG婴洼,ARG指令不會人保留在最終鏡像中。

ARG DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y ...

7.ARG

ARG構(gòu)建參數(shù)與ENV作用一致,不過作用域不一樣,ARG設(shè)置的環(huán)境變量僅對Dockerfile內(nèi)有效科展,也就是說只有docker build的過程中有效浙于,構(gòu)建好的鏡像內(nèi)不存在此環(huán)境變量讹挎。

構(gòu)建命令docker build中可以用--build-arg <參數(shù)名>=<值>來覆蓋,ARG指令格式如下:

ARG <參數(shù)名>[=默認值]

如果ARG指令具有默認值,并且在構(gòu)建時未傳遞任何值国葬,則構(gòu)建時會使用默認值贤徒,相反如果未設(shè)置默認值,并且在構(gòu)建中未傳遞任何值胃惜,那么構(gòu)建時會輸出警告信息泞莉。

8.ADD

ADD指令是指將宿主機的文件或目錄復(fù)制到鏡像文件系統(tǒng)中指定的路徑哪雕,其語法格式有兩種:

ADD [--chown=<user>:<group>] <src>... <dest>

ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]

每個可以使用通配符船殉,并且匹配將使用Go的filepath.Match規(guī)則進行,例如:

要添加所有以“hom”開頭的文件:

ADD hom* /mydir/

“斯嚎?”可以替換任意一個字符利虫,例如:

ADD hom?.txt /mydir/

是指構(gòu)建容器的路徑,可以是絕對路徑堡僻,也可以是相對路徑糠惫,但這個相對路徑是相對于WORKDIR的路徑。如以下示例是將“test.txt”文件添加到/relativeDir/钉疫。

ADD test.txt relativeDir/

下面的示例則是將“test.txt”添加到相對路徑/absoluteDie/中硼讽。

ADD test.txt /absoluteDir/

如果路徑中包含一些特字符,那么需要按照Golang規(guī)則轉(zhuǎn)義那些路徑牲阁,以防止在解析過程中將它們視為匹配的模式固阁,如要添加名為sarr[1].txt的文件。

ADD sarr[[]1].txt /mydir/

路徑必須是構(gòu)建內(nèi)容的一個內(nèi)部路徑城菊,不能添加類似于ADD ../path /path备燃,因為docker build的第一步是將上下文目錄和子目錄發(fā)送到docker守護進程。

如果是URL凌唬,而不以斜杠結(jié)尾并齐,則從URL下載文件并將其復(fù)制到。

如果是URL,而以斜杠結(jié)尾况褪,則從URL推斷文件名撕贞,并將文件下載到/,例如ADD http://chuanshi.com/foobar /窝剖,將創(chuàng)建文件/foobar麻掸,該URL必須具有正確的路徑,以便在這種情況下可以找到適當?shù)奈募?/p>

如果是目錄赐纱,則復(fù)制目錄的整個內(nèi)容脊奋,包括文件系統(tǒng)元數(shù)據(jù)。

如果是任何其他類型的文件疙描,則會將其及其元數(shù)據(jù)一起單獨復(fù)制诚隙,在這種情況下,如果以斜杠結(jié)尾起胰,則它將被視為目錄久又,并且的內(nèi)容將被寫在/base()中。

如果直接或由于使用通配符而指定多個資源效五,則必須是目錄地消,并且必須以斜杠結(jié)尾。

如果不以斜杠結(jié)尾畏妖,則將其視為常規(guī)文件脉执,并且的內(nèi)容將被寫入。

如果不存在戒劫,則會與路徑中所有缺少的目錄一起創(chuàng)建它半夷。

1.ADD的優(yōu)點:在執(zhí)行為tar壓縮文件的話,壓縮格式為gzip迅细、gzip2以及xz的情況下巫橄,會自動復(fù)制并解壓到。

2.ADD的缺點:在不解壓的前提下茵典,無法復(fù)制tar壓縮文件湘换,會令鏡像構(gòu)建緩存失效,從而可能會令鏡像構(gòu)建變得比較緩慢统阿,具體是否使用彩倚,可以根據(jù)是否需要自動解壓來決定。

9.COPY

復(fù)制指令砂吞,從上下文目錄中復(fù)制文件或者目錄到容器里指定路徑署恍,通常有以下兩種格式:

COPY [--chown=<user>:<group>] <src>... <dest>

COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]

COPY指令表示從復(fù)制新文件或目錄,并將它們添加到容器的文件系統(tǒng)中蜻直,路徑為盯质。

可以指定多個資源袁串,但是文件和目錄的路徑將被解釋為相對于構(gòu)建上下文。

每個可能包含通配 符呼巷,并且匹配將合作Go人filepath.Match規(guī)則進行囱修。

例如要添加所有"hom"開頭的文件:

COPY home* /mydir/

"?"表示可以匹配任意一個字符:

COPY hom?.txt /mydir/

是指構(gòu)建容器的路徑,可以是絕對路徑王悍,也可以是相對路徑破镰,但這個相對路徑是相對于WORKDIR的路徑。如以下示例是將“test.txt”文件添加到/relativeDir/压储。

COPY test.txt relativeDir/

下面的示例則是將“test.txt”添加到相對路徑/absoluteDie/中鲜漩。

COPY test.txt /absoluteDir/

如果路徑中包含一些特字符,那么需要按照Golang規(guī)則轉(zhuǎn)義那些路徑集惋,以防止在解析過程中將它們視為匹配的模式孕似,如要添加名為sarr[1].txt的文件。

COPY sarr[[]1].txt /mydir/

路徑必須是構(gòu)建內(nèi)容的一個內(nèi)部路徑刮刑,不能添加類似于COPY ../path /path喉祭,因為docker build的第一步是將上下文目錄和子目錄發(fā)送到docker守護進程。

如果是目錄雷绢,則復(fù)制目錄的整個內(nèi)容泛烙,包括文件系統(tǒng)無數(shù)據(jù),目錄本身不會被復(fù)制翘紊,只是其內(nèi)容被復(fù)制蔽氨。

如果是任何其他類型的文件,則會將其及其元數(shù)據(jù)一起單獨復(fù)制霞溪,在這種情況下孵滞,如果以斜杠結(jié)尾中捆,則它將被視為目錄鸯匹,并且的內(nèi)容將被寫在/base()中。

如果直接或由于使用通配符而指定多個資源泄伪,則必須是目錄殴蓬,并且必須以斜杠結(jié)尾。

如果不以斜杠結(jié)尾蟋滴,則將其視為常規(guī)文件染厅,并且的內(nèi)容將被寫入。

如果不存在津函,則會與路徑中所有缺少的目錄一起創(chuàng)建它肖粮。

10.ENTRYPOINT

類似于CMD指令,但其不會被docker run指令運行參數(shù)所覆蓋尔苦,并且這些命令行參數(shù)會被當作參數(shù)送給ENTRYPOINT指令指定的程序涩馆。

但是如果運行docker run時使用了--entrypoint選項行施,將覆蓋CMD指令指定的程序。

其語法格式有以下兩種:

#exec格式

ENTRYPOINT ["executable", "param1", "param2"]

#shell格式

ENTRYPOINT command param1 param2

ENTRYPOINT的優(yōu)點在執(zhí)行docker run的時候可以指定ENTRYPOINT運行所需要的參數(shù)魂那。

但如果Dockerfile中如果存在多個ENTRYPOINT指令時蛾号,只有最后一個會生效。

可以將ENTRYPOINT與CMD命令搭配使用涯雅,一般是變參才會使用CMD鲜结,這里的CMD等于是在給ENTRYPOINT傳參。

例如活逆,通過Dockerfile構(gòu)建了一個nginx:V1.0的鏡像精刷。

FROM nginx

ENTRYPOINT ["nginx", "-c"] # 定參

CMD ["/etc/nginx/nginx.conf"] # 變參

如果在運行容器時,不傳參運行蔗候,

root@ubunhomhome/test# docker run -it nginx:v1.0

容器內(nèi)則會默認運行以下命令贬养,啟動主進程。

nginx -c /etc/nginx/nginx.conf

如果在運行容器時傳參運行琴庵,

root@ubunhomhome/test# docker run -it nginx:v1.0 -c /etc/nginx/new_nginx.conf

容器內(nèi)會默認運行以下命令误算,啟動主進程。

nginx -c /etc/nginxnew_nginx.conf

11.VOLUME

VOLUME指令在后面的章節(jié)會進行詳細的介紹迷殿,在本小節(jié)中不做介紹

12.USER

USER指令用于指定執(zhí)行后續(xù)命令的用戶和用戶組儿礼,這邊只是切換后續(xù)指令執(zhí)行的用戶(用戶和用戶組必須提前已經(jīng)存在)。其語法格式如下:

USER <user>[:<group>]

#or

USER <UID>[:<GID>]

13.WORKDIR

WORKDIR指令表示指定工作目錄庆寺,該指定的目錄必須提前創(chuàng)建好蚊夫,docker build構(gòu)建鏡像過程中的,每個RUN命令都是新建的一層懦尝,只有通過WORKDIR創(chuàng)建才會一直存在知纷。其語法格式如下:

WORKDIR /path/to/workdir

WORKDIR指令可在Dockerfile中多次使用,如果提供了相對路徑陵霉,則它將相對于上一個WORKDIR指令的路徑來創(chuàng)建目錄琅轧,如:

WORKDIR /a

WORKDIR b

WORKDIR c

RUN pwd

該Dockerfile中最后一個pwd命令的輸出為/a/b/c。

WORKDIR指令也可以解析ENV設(shè)置的環(huán)境變量踊挠,如:

ENV DIRPATH=/path

WORKDIR $DIRPATH/$DIRNAME

RUN pwd

該Dockerfile中最后一個pwd命令的輸出為/path/$DIRNAME乍桂。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市效床,隨后出現(xiàn)的幾起案子睹酌,更是在濱河造成了極大的恐慌,老刑警劉巖剩檀,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件憋沿,死亡現(xiàn)場離奇詭異,居然都是意外死亡沪猴,警方通過查閱死者的電腦和手機辐啄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進店門甥绿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人则披,你說我怎么就攤上這事共缕。” “怎么了士复?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵图谷,是天一觀的道長。 經(jīng)常有香客問我阱洪,道長便贵,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任冗荸,我火速辦了婚禮承璃,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蚌本。我一直安慰自己盔粹,他們只是感情好,可當我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布程癌。 她就那樣靜靜地躺著舷嗡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪嵌莉。 梳的紋絲不亂的頭發(fā)上进萄,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天,我揣著相機與錄音锐峭,去河邊找鬼中鼠。 笑死,一個胖子當著我的面吹牛沿癞,可吹牛的內(nèi)容都是我干的援雇。 我是一名探鬼主播,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼抛寝,長吁一口氣:“原來是場噩夢啊……” “哼熊杨!你這毒婦竟也來了曙旭?” 一聲冷哼從身側(cè)響起盗舰,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎桂躏,沒想到半個月后钻趋,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡剂习,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年蛮位,在試婚紗的時候發(fā)現(xiàn)自己被綠了较沪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡失仁,死狀恐怖尸曼,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情萄焦,我是刑警寧澤控轿,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站拂封,受9級特大地震影響茬射,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜冒签,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一在抛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧萧恕,春花似錦刚梭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至惰说,卻和暖如春磨德,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背吆视。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工典挑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人啦吧。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓您觉,卻偏偏與公主長得像,于是被迫代替她去往敵國和親授滓。 傳聞我的和親對象是個殘疾皇子琳水,可洞房花燭夜當晚...
    茶點故事閱讀 44,871評論 2 354

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