使用Dockerfile構(gòu)建自己的鏡像

格式

  1. 所有的指令是非大小寫敏感的,但習(xí)慣寫為大寫有助于與你的參數(shù)做區(qū)分
  2. 所有的指令按照Dockerfile文件順序執(zhí)行
  3. 一個(gè)Dockerfile必須以FROM指令開始(但可以在解析器指令parse derictive、注釋comments或全局參數(shù)ARGs后)
  4. FROM前可以有一個(gè)或多個(gè)ARG,這些ARG中聲明的變量將會(huì)在FROM行中使用
  5. 與shell,python等腳本語言類似Dockerfile中以#開頭的行會(huì)被當(dāng)做注釋,如果它出現(xiàn)在Dockerfile文件的最上方并且是合法的解析器指令探越。它將會(huì)當(dāng)作解析器處理萌业,同一個(gè)解析器只會(huì)處理一次侧蘸,第二次聲明也將會(huì)當(dāng)作注釋處理。(合法的解析器包括syntax和escape)

.dockerignore

構(gòu)建docker鏡像時(shí)有上下文概念偎捎,例如以docker build -t 鏡像名 .命令構(gòu)建鏡像是上下文即為Dockerfile所在目錄(當(dāng)然執(zhí)行該命令的工作目錄也在Dockerfile所在目錄)蠢终。
docker 構(gòu)建鏡像時(shí)會(huì)將上下文中的所有文件拷貝到docker的構(gòu)建進(jìn)程中,就像.gitignore一樣聲明在.dockerignore中的文件或文件夾在拷貝時(shí)會(huì)被忽略鸭限。

構(gòu)建指令

  1. FROM
    所有Dockerfile最先執(zhí)行的指令(當(dāng)然最先是在排除前文提到的解析器指令和參數(shù)等的前提下蜕径,因?yàn)檫@幾個(gè)指令都是可選的)
    該指令指定一個(gè)基礎(chǔ)鏡像(也可以理解為父鏡像)两踏。為之后一系列操作提供基礎(chǔ)運(yùn)行環(huán)境败京。
    該指令可以使用已定義過的ARG,使用方式為${參數(shù)名},與shell很想對嗎梦染?沒錯(cuò)之后還會(huì)有很多相似之處赡麦。
  2. RUN
    RUN指令用于在構(gòu)建容器時(shí)執(zhí)行你指定的任意命令。
    RUN指令有兩種格式

shell格式
RUN /bin/bash -c 'source \$HOME/.bashrc; \
echo $HOME'

改格式下你可以使用 \ 來在另一行編寫你未完成的單個(gè)命令帕识,并且可以使用${}操作符泛粹,json格式則不可以。

exec格式
RUN ["/bin/bash", "-c", "echo hello"]

exec格式會(huì)被轉(zhuǎn)換為一個(gè)json數(shù)組肮疗,所以你因該使用雙引號"來包裹你額單詞而不是單引號',另外在該格式中應(yīng)避免反斜杠 \尤其是在windows中\標(biāo)識了windows的文件目錄晶姊。

  1. CMD
    一個(gè)Dockerfile中只能有一個(gè)CMD命令,如果寫了多個(gè)那么只有最后一個(gè)生效伪货。它的目的是為容器提供一個(gè)默認(rèn)執(zhí)行應(yīng)用们衙。
    該命令會(huì)被命令行參數(shù)所替換例如如果啟動(dòng)時(shí)執(zhí)行命令為docker run -it 容器名 /bin/sh則CMD內(nèi)容將被替換為 /bin/sh
    CMD命令一共有三種格式

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

該格式是最推薦使用的格式

作為ENTRYPOINT的默認(rèn)參數(shù)
CMD ["param1","param2"]

當(dāng)它作為ENTRYPOINT的參數(shù)的時(shí)候ENTRYPOINT和CMD都必須是json數(shù)組的格式。

shell格式
CMD command param1 param2

使用改格式默認(rèn)會(huì)在/bin/sh -c中執(zhí)行碱呼,如果不想使用/bin/sh -c執(zhí)行命令請使用exec格式

  1. LABLE
    LABLE為構(gòu)建的鏡像添加一些key-value格式的元數(shù)據(jù)蒙挑,和RUN一樣可以使用反斜杠 \ 在下一行完成單條過長的元數(shù)據(jù)。
    例:
FROM ubuntu:18.04
WORKDIR /usr/local
LABEL wxm="wxm530" \
      alming="alming530"

構(gòu)建完成后 docker inspect 鏡像名

"WorkingDir": "/usr/local",
"Entrypoint": null,
"OnBuild": null,
"Labels": {
     "alming": "alming530",
      "wxm": "wxm530"
}

LABLE包包括前鏡像和父鏡像的LABLE,如果重復(fù)了以最新的為準(zhǔn).

  1. EXPOSE
    EXPOSE指定Docker容器運(yùn)行時(shí)向外暴露的端口愚臀,可以指定TCP或UDP協(xié)議端口忆蚀,默認(rèn)采用TCP協(xié)議。指令格式EXPOSE 80/tcp EXPOSE 80/udp
  2. ENV
    ENV即環(huán)境變量,它有兩種格式

ENV <key> <value>

該格式設(shè)置一個(gè)單個(gè)的環(huán)境變量馋袜,第一個(gè)完整的字符串是key key+空格后的所有值都是value男旗,
它會(huì)被其他環(huán)境變量所解析,如果沒有轉(zhuǎn)義不應(yīng)該在改格式中寫引號"桃焕。(這里不理解剑肯,只是翻譯了一下官方文檔)

ENV <key>=<value> ...

改格式允許在一行定義多個(gè)環(huán)境變量,以空格分隔观堂。如果環(huán)境變量本身需要空格將有空格的變量使用引號"括起來或使用\來轉(zhuǎn)義空格让网。

注意ENV添加的環(huán)境變量對于容器來說是持久的。如果需要臨時(shí)的變量則使用RUN <key>=<value> <command>.

  1. ADD
  • ADD指令用于將主機(jī)或者某個(gè)url上的文件資源拷貝到將要構(gòu)建的鏡像當(dāng)中师痕。
  • 源文件地址可以使用Go’s filepath.Match rules.解析規(guī)則的通配符溃睹。
  • 目的地址是目標(biāo)容器的絕對地址或者是WORKDIR的相對地址(關(guān)于WORKDIR參照WORKDIR文檔)。
  • 如果源地址中包含特殊字符則需要按照Go語言的轉(zhuǎn)義規(guī)則將它們轉(zhuǎn)義胰坟。
  • 添加到容器中的文件默認(rèn)由GID和UID為0的用戶創(chuàng)建因篇,如果想改變使用--chown參數(shù),這一部分詳細(xì)參照官方文檔。
  • 如果添加的文件是歸檔文件還會(huì)被默認(rèn)加壓笔横。
    該指令有兩種格式竞滓。

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

  1. COPY
    COPY指令與ADD基本一致,但它不會(huì)解壓添加到容器中的歸檔文件
  2. ENTRYPOINT
    ENTRYPOINT和CMD類似都用于指定容器啟動(dòng)時(shí)容器內(nèi)執(zhí)行的命令或執(zhí)行可執(zhí)行文件吹缔,CMD中的指令最終都會(huì)以參數(shù)的形式傳遞給ENTRYPOINT(前提是ENTRYPOINT是exec格式)商佑。
    ENTRYPOINT有兩種格式

shell格式
ENTRYPOINT command param1 param2

改格式不會(huì)接收CMD作為參數(shù),但有一個(gè)缺點(diǎn)就是使用docker stop命令無法正常關(guān)閉容器內(nèi)正在運(yùn)行的應(yīng)用,(個(gè)人理解為對于容器中運(yùn)行的應(yīng)用來說容器停止時(shí)它們都是強(qiáng)制退出的厢塘,也就是說如果程序中有結(jié)束程序的鉤子函數(shù)可能無法被正常執(zhí)行)

所以使用改格式時(shí)需要在命令前添加exec例如ENTRYPOINT exec top -b

exec格式
ENTRYPOINT ["executable", "param1", "param2"]

該格式下每個(gè)參數(shù)都是一個(gè)字符不能連寫例如有兩個(gè)參數(shù)-c-t則不能寫成["command","-c -t" ]因該寫成["command","-c","-c"]并且所有參數(shù)都要使用雙引號""茶没,所有寫在CMD中的命令將會(huì)自動(dòng)添加在數(shù)組的尾部作為參數(shù),同時(shí)CMD內(nèi)容可被啟動(dòng)時(shí)命令行內(nèi)容替換晚碾,所以可以使用命令行替換CMD內(nèi)容繼而追加道ENTRYPOINT中抓半。
例:

//Dockerfile
FROM ubuntu:18.04
WORKDIR /usr/local
ENTRYPOINT ["echo"]
CMD wxm

執(zhí)行docker build -t wxm .構(gòu)建鏡像
先不加參數(shù)運(yùn)行docker run -it wxm運(yùn)行結(jié)果

[alming@localhost docker]$ docker run -it wxm
/bin/sh -c wxm
[alming@localhost docker]$ 

可以看到wxm被打印說明CMD中內(nèi)容確實(shí)被追加到ENTRYPOINT中了,同時(shí)看到還打印了/bin/sh -c側(cè)面說明了CMD中命令默認(rèn)由/bin/sh -c 執(zhí)行格嘁,這一點(diǎn)官方文檔中也有提及

截取自官方文檔

接下來運(yùn)行容器時(shí)指定自定義參數(shù)docker run -it wxm alming

[alming@localhost docker]$ docker run -it wxm alming
alming
[alming@localhost docker]$ 

可以看到參數(shù)被正確替換并傳遞笛求。
另外如果要為容器中的可執(zhí)行文件編寫可執(zhí)行腳本以在ENTRYPOINT中執(zhí)行需要注意使用exec加gosu啟動(dòng)可執(zhí)行文件這樣可以保證啟動(dòng)的進(jìn)程的PID為1從而可以接收到docker stop傳過來的停止信號從而優(yōu)雅的結(jié)束該進(jìn)程。目的也是為了保證程序退出前的準(zhǔn)備工作正常完成糕簿。
下面是官方示例:

#!/usr/bin/env bash
set -e

if [ "$1" = 'postgres' ]; then
    chown -R postgres "$PGDATA"

    if [ -z "$(ls -A "$PGDATA")" ]; then
        gosu postgres initdb
    fi

    exec gosu postgres "$@"
fi
exec "$@"
  1. VOLUME
    在容器中創(chuàng)建你聲明的掛載點(diǎn)探入,即創(chuàng)建一個(gè)目錄。并且會(huì)默認(rèn)關(guān)聯(lián)到宿主機(jī)/var/lib/docker/volume下的一個(gè)文件夾下的_data文件夾冶伞。該文件夾由docker生成名稱是一個(gè)hash碼
[root@192 volumes]# pwd
/var/lib/docker/volumes
[root@192 volumes]# ls
0a31112d023a994c3dc4ed945a75fa4c55ce9d94ff80c200d2574bb0270df3d3
0f61fd7fdf69653ab4d5dc6c576b5e809553c83914c8c295bfc3511c56ac50eb
10b2add0f578d26f79fc9ac69df126ab93793314d98ebe37c93e97aa545486bf
17c764a4a52320ce2a85ec7ccab81c6b3845e53225bfc955d3308dc09ead7618

和手使用-v指定的文件夾一樣和容器內(nèi)的文件夾內(nèi)容同步新症。
其值可以是純字符轉(zhuǎn)也可以是json數(shù)組

  1. USER
    USER指令用來設(shè)置用戶名(或UID)組名(或GID)。設(shè)置完成后响禽,接下來的RUN,ENTRYPOINT,CMD中所執(zhí)行的命令都有該用戶完成徒爹。
    格式

USER <UID>[:<GID>]
or
USER <user>[:<group>]

  1. WORKDIR
    WORKDIR指令為RUN,CMD,ENTRYPOINT,ADD,COPY指定工作空間
    格式

WORKDIR /path/to/workdir

它可以定義多次并且每次都會(huì)以上一個(gè)WORKDIR指令為相對目錄荚醒,官方示例為

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

最終打印結(jié)果為/a/b/c
WORKDIR 還可以解析之前定義過的ENV中的內(nèi)容,但注意只能解析Dockerfile中定義的ENV系統(tǒng)環(huán)境變量是取不到的隆嗅,官方示例:

ENV DIRPATH /path
WORKDIR $DIRPATH/$DIRNAME
RUN pwd

最總打印結(jié)果為/path/$DIRNAME

  1. ARG
    用戶在使用docker build指令時(shí)可通過 --build-arg <varname>=<value>將參數(shù)傳遞給Dockerfile中聲明的ARG中以供之后通過$參數(shù)名使用界阁。
    同時(shí)它可以有默認(rèn)值ARG user1=someuser,并且其他指令只能調(diào)用在它本身之前聲明過的ARG。
    注意如果ENV定義的變量名和ARG重復(fù)了ENV的值將會(huì)覆蓋ARG的值
    Docker中有一些預(yù)定義的ARG這些ARG不需要你聲明也可以使用包括
  • HTTP_PROXY
  • http_proxy
  • HTTPS_PROXY
  • https_proxy
  • FTP_PROXY
  • ftp_proxy
  • NO_PROXY
  • no_proxy
    這些預(yù)定義變量將不會(huì)被docker history輸出
  1. ONBUILD
    ONBUILD指定當(dāng)子鏡像被構(gòu)建時(shí)需要執(zhí)行的指令胖喳,其中聲明的指令將會(huì)被插入到子鏡像的FROM指令之后執(zhí)行泡躯。
    注意,ONBUILD不可嵌套使用并且不會(huì)觸發(fā)FROM指令丽焊。
  2. STOPSIGNAL
    STOPSIGNAL指定使用docker stop停止容器時(shí)容器內(nèi)應(yīng)用程序的終止行為较剃,格式為

STOPSIGNAL signal

以下內(nèi)容出自stackoverflow非官方文檔,文檔未對此指令做細(xì)致解釋技健。原文

可選取值為SIGKILL,SIGTERM ,SIGINT
其中SIGTERMSIGINT可以正常關(guān)閉正在運(yùn)行的應(yīng)用写穴,SIGKILL則不能
SIGKILL相當(dāng)于kill -9 <PID>
SIGTERM 相當(dāng)于kill <PID>
SIGINT相當(dāng)于Ctrl + c

  1. HEALTHCHECK
    HEALTHCHECK目的是在容器中運(yùn)行特定的指令以檢查容器中的應(yīng)用設(shè)否正常工作,他也有兩種格式:

HEALTHCHECK [OPTIONS] CMD command

HEALTHCHECK NONE
繼承自父鏡像雌贱,默認(rèn)不進(jìn)行任何檢測

例如以下指令規(guī)定每5分鐘像web服務(wù)器發(fā)送請求并判斷是否在3s內(nèi)返回從而判斷web服務(wù)器是否正常工作啊送。

  1. SHELL
    SHELL指令用于切換RUN,CMD,ENTRYPOINT的默認(rèn)shell,默認(rèn)情況下linux使用的是["/bin/sh", "-c"]Windows使用的是["cmd", "/S", "/C"]通常用于當(dāng)默認(rèn)shell執(zhí)行不了某個(gè)命令時(shí)使用SHELL指令切換shell執(zhí)行完成后再通過SHELL指令切回原來的shell.
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市欣孤,隨后出現(xiàn)的幾起案子馋没,更是在濱河造成了極大的恐慌,老刑警劉巖降传,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件篷朵,死亡現(xiàn)場離奇詭異,居然都是意外死亡搬瑰,警方通過查閱死者的電腦和手機(jī)款票,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進(jìn)店門控硼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來泽论,“玉大人,你說我怎么就攤上這事卡乾∫磴玻” “怎么了?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵幔妨,是天一觀的道長鹦赎。 經(jīng)常有香客問我,道長误堡,這世上最難降的妖魔是什么古话? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮锁施,結(jié)果婚禮上陪踩,老公的妹妹穿的比我還像新娘杖们。我一直安慰自己,他們只是感情好肩狂,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布摘完。 她就那樣靜靜地躺著,像睡著了一般傻谁。 火紅的嫁衣襯著肌膚如雪孝治。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天审磁,我揣著相機(jī)與錄音谈飒,去河邊找鬼。 笑死态蒂,一個(gè)胖子當(dāng)著我的面吹牛步绸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播吃媒,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼瓤介,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了赘那?” 一聲冷哼從身側(cè)響起刑桑,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎募舟,沒想到半個(gè)月后祠斧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拱礁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年琢锋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片呢灶。...
    茶點(diǎn)故事閱讀 39,779評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡吴超,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出鸯乃,到底是詐尸還是另有隱情鲸阻,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布缨睡,位于F島的核電站鸟悴,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏奖年。R本人自食惡果不足惜细诸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望陋守。 院中可真熱鬧震贵,春花似錦鹏浅、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蝙眶,卻和暖如春季希,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背幽纷。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工式塌, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人友浸。 一個(gè)月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓峰尝,卻偏偏與公主長得像,于是被迫代替她去往敵國和親收恢。 傳聞我的和親對象是個(gè)殘疾皇子武学,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評論 2 354