2019-05-07 Dockerfile 詳解

本文僅為個(gè)人學(xué)習(xí)記錄. 教程來源Docker--從入門到實(shí)踐

FROM 指定基礎(chǔ)鏡像

FROM nginx

FROM 有一個(gè)比較特殊的鏡像(空鏡像)

FROM scratch

一般 golang 程序會(huì)直接使用FROM scratch.


RUN 執(zhí)行命令

run指令有兩種格式

  • shell格式
RUN echo 'hello docker'
  • exec格式
RUN apt-get update
RUN apt-get install -y gcc

注意:Dockerfile每一個(gè)指令都會(huì)構(gòu)建一層,不得超過127層

所以很多時(shí)候我們會(huì)使用 && 來減少構(gòu)建的層數(shù)
例如上例可改寫為

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

Dockerfile nginx 實(shí)例

FROM nginx
RUN echo '<h1>Hello,Docker!!</h1>' > /usr/share/nginx/html/index.html

構(gòu)建命令

docker build -t nginx:v3 .

運(yùn)行命令

docker run --name webserver -d -p 80:80 nginx:v3

COPY 復(fù)制文件

COPY 指令將從構(gòu)建上下文目錄中 <源路徑> 的文件/目錄復(fù)制到新的一層的鏡像內(nèi)的 <目標(biāo)路徑> 位置。

COPY [--chown=<user>:<group>]<源路徑> ... <目標(biāo)路徑>
COPY [--chown=<user>:<group>] ["<源路徑1>",... "<目標(biāo)路徑>"]

<目標(biāo)路徑> 可以是容器內(nèi)的絕對路徑论悴,也可以是相對于工作目錄的相對路徑(工作目錄可以用 WORKDIR 指令來指定)。目標(biāo)路徑不需要事先創(chuàng)建耻讽,如果目錄不存在會(huì)在復(fù)制文件前先行創(chuàng)建缺失目錄针肥。
例子:

COPY package.json /usr/src/app/

這里源路徑可以使用通配符,其通配符規(guī)則要滿足 go 的 filepath.Match規(guī)則

例如:

COPY hom* /mydir/
COPY hom?.txt /mydir/

ADD 更高級的復(fù)制文件 (雖然很高級但不建議使用)

ADD [--chown=<user>:<group>]<源路徑> ... <目標(biāo)路徑>
ADD [--chown=<user>:<group>] ["<源路徑1>",... "<目標(biāo)路徑>"]

ADD 指令和 COPY 的格式和性質(zhì)基本一致。但是在 COPY 基礎(chǔ)上增加了一些功能

比如 <源路徑> 可以是一個(gè) URL具帮,這種情況下蜂厅,Docker 引擎會(huì)試圖去下載這個(gè)鏈接的文件放到 <目標(biāo)路徑> 去。下載后的文件權(quán)限自動(dòng)設(shè)置為 600唇跨,如果這并不是想要的權(quán)限改橘,那么還需要增加額外的一層 RUN 進(jìn)行權(quán)限調(diào)整唧龄,另外既棺,如果下載的是個(gè)壓縮包耽梅,需要解壓縮眼姐,也一樣還需要額外的一層 RUN 指令進(jìn)行解壓縮众旗。所以不如直接使用 RUN 指令贡歧,然后使用 wget 或者 curl 工具下載利朵,處理權(quán)限、解壓縮著洼、然后清理無用文件更合理年碘。因此屿衅,這個(gè)功能其實(shí)并不實(shí)用涤久,而且不推薦使用

注意 ADD 指令會(huì)令鏡像構(gòu)建緩存失效响迂,從而可能會(huì)令鏡像構(gòu)建變得比較緩慢。因此在 COPY 和 ADD 指令中選擇的時(shí)候然遏,可以遵循這樣的原則待侵,所有的文件復(fù)制均使用 COPY 指令怨酝,僅在需要自動(dòng)解壓縮的場合使用 ADD农猬。


CMD 容器啟動(dòng)命令

Docker 不是虛擬機(jī)售淡,容器就是進(jìn)程。既然是進(jìn)程楔壤,那么在啟動(dòng)容器的時(shí)候蹲嚣,需要指定所運(yùn)行的程序及參數(shù)隙畜。CMD 指令就是用于指定默認(rèn)的容器主進(jìn)程的啟動(dòng)命令的

CMD指令的格式和RUN相似,也是兩種格式:

#shell格式
CMD <命令>
#exec格式
CMD ["可執(zhí)行文件","參數(shù)1","參數(shù)2"...]

在指令格式上,一般推薦使用 exec 格式言询,這類格式在解析時(shí)會(huì)被解析為 JSON 數(shù)組运杭,因此一定要使用雙引號 "辆憔,而不要使用單引號熊榛。

如果使用 shell 格式的話, 實(shí)際的命令會(huì)被包裝為 sh -c 的參數(shù)的形式進(jìn)行執(zhí)行.

CMD echo $HOME

在實(shí)際執(zhí)行中, 會(huì)將其變更為:

CMD [ "sh", "-c", "echo $HOME" ]

這就是為什么我們可以使用環(huán)境變量的原因, 因?yàn)檫@些環(huán)境變量會(huì)被shell 進(jìn)行解析處理, 提到CMD 就不得不提容器中應(yīng)用在前臺執(zhí)行和后臺執(zhí)行的問題. 這是初學(xué)者常出現(xiàn)的一個(gè)混淆.

Docker不是虛擬機(jī), 容器中的應(yīng)用都應(yīng)該以前臺執(zhí)行,而不是像虛擬機(jī)/物理機(jī)那樣,用upstart/systemd去啟動(dòng)后臺服務(wù), 容器內(nèi)沒有后臺服務(wù)的概念

一些初學(xué)者將CMD寫為

CMD service nginx start

然后發(fā)現(xiàn)容器執(zhí)行后就立即退出了,甚至在容器內(nèi)去使用systemctl 命令,結(jié)果發(fā)現(xiàn)根本執(zhí)行不了.這就是因?yàn)闆]搞明白前臺,后臺的概念, 沒有區(qū)分容器和虛擬機(jī)的差異,依舊用傳統(tǒng)虛擬機(jī)的角度去理解容器

對于容器而言, 其啟動(dòng)程序就是容器應(yīng)用進(jìn)程, 容器就是為了主進(jìn)程而存在的, 主進(jìn)程退出 , 容器就失去了存在的意義,從而退出, 其他輔助進(jìn)程不是他需要關(guān)心的東西

而使用 service nginx start命令 則是希望upstart來以"后臺守護(hù)進(jìn)程"的形式啟動(dòng)nginx服務(wù), 但剛才說了 CMD service nginx start 會(huì)被理解為 CMD [ "sh", "-c", "echo $HOME" ],因此主進(jìn)程實(shí)際上是sh.那么當(dāng)service nginx start命令結(jié)束后 , sh 也就結(jié)束了,sh作為主進(jìn)程退出了, 自然就會(huì)讓容器也跟著退出

正確的做法是 直接執(zhí)行nginx可執(zhí)行文件, 并且要求以前臺的形式運(yùn)行.
比如:

CMD ["nginx", "-g", "deamon off"]

個(gè)人理解:
推薦使用 exec格式的用意是為了避免類似sh -c的命令干擾


ENTRYPOINT (入口點(diǎn))

ENTRYPOINT 的格式和RUN指令格式一樣, 分為 execshell
ENTRYPOINT 的目的和CMD一樣都是在指定容器啟動(dòng)程序及參數(shù). ENTRYPOINT 在運(yùn)行是也可以替代,不過比CMD略顯繁瑣, 需要通過docker run的參數(shù)--entrypoint來指定

當(dāng)指定了ENTRYPOINT 后, CMD的含義就發(fā)生了改變, 不再是直接的運(yùn)行其命令, 而是將CMD的內(nèi)容當(dāng)作參數(shù)傳給ENTRYPOINT指令.可以理解為:

<ENTRYPOINT> "<CMD>"

場景一: 讓鏡像變成像命令一樣使用

假設(shè)我們需要一個(gè)得知自己當(dāng)前公網(wǎng) IP 的鏡像营搅,那么可以先用 CMD 來實(shí)現(xiàn):

FROM ubuntu:18.04
RUN apt-get update \
    &&apt-get install -y curl \
    &&rm -rf /var/lib/apt/lists/*
CMD ["curl", "-s" ,"https://ip.cn"]

假如我們使用 docker build -t myip . 來構(gòu)建鏡像的話, 如果我們需要查詢當(dāng)前公網(wǎng)IP, 只需要執(zhí)行

docker run myip

這里遇到一個(gè)問題, 如果我們想用curl -i的話就會(huì)出現(xiàn)問題
所以這里就引申出了ENTRYPOINT的用法

FROM ubuntu:18.04
RUN apt-get update \
    &&apt-get install -y curl \
    &&rm -rf /var/lib/apt/lists/*
ENTRYPOINT ["curl","-s","https://ip.cn"]

ENV 設(shè)置環(huán)境變量

格式有兩種

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

這個(gè)指令很簡單,就是設(shè)置環(huán)境變量而已休蟹,無論是后面的其它指令,如 RUN哪轿,還是運(yùn)行時(shí)的應(yīng)用杨耙,都可以直接使用這里定義的環(huán)境變量珊膜。

.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市堪遂,隨后出現(xiàn)的幾起案子溶褪,更是在濱河造成了極大的恐慌猿妈,老刑警劉巖彭则,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件输瓜,死亡現(xiàn)場離奇詭異尤揣,居然都是意外死亡北戏,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進(jìn)店門蠕嫁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人奶镶,你說我怎么就攤上這事厂镇∞嘈牛” “怎么了迄靠?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長吠式。 經(jīng)常有香客問我特占,道長是目,這世上最難降的妖魔是什么懊纳? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任功舀,我火速辦了婚禮,結(jié)果婚禮上阱佛,老公的妹妹穿的比我還像新娘翩蘸。我一直安慰自己催首,他們只是感情好郎任,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著霉猛,像睡著了一般惜浅。 火紅的嫁衣襯著肌膚如雪赡矢。 梳的紋絲不亂的頭發(fā)上吹散,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天刃唐,我揣著相機(jī)與錄音画饥,去河邊找鬼抖甘。 笑死衔彻,一個(gè)胖子當(dāng)著我的面吹牛艰额,可吹牛的內(nèi)容都是我干的柄沮。 我是一名探鬼主播祖搓,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼哈扮!你這毒婦竟也來了蚓再?” 一聲冷哼從身側(cè)響起摘仅,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤六荒,失蹤者是張志新(化名)和其女友劉穎掏击,沒想到半個(gè)月后砚亭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體捅膘,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了沐寺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片混坞。...
    茶點(diǎn)故事閱讀 40,030評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖厨诸,靈堂內(nèi)的尸體忽然破棺而出微酬,到底是詐尸還是另有隱情,我是刑警寧澤滓走,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布比吭,位于F島的核電站衩藤,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏娄蔼。R本人自食惡果不足惜岁诉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望坠韩。 院中可真熱鬧只搁,春花似錦、人聲如沸焰望。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽传趾。三九已至墨缘,卻和暖如春镊讼,著一層夾襖步出監(jiān)牢的瞬間蝶棋,已是汗流浹背玩裙。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留决侈,地道東北人赖歌。 一個(gè)月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像展父,于是被迫代替她去往敵國和親犯祠。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評論 2 355

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