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

1杂靶、 Dockerfile基本結(jié)構(gòu)

Dockerfile由一行行命令語句組成持搜,并且支持以#開頭的注釋行。
一般而言辞居,Dockerfile分為四部分:基礎(chǔ)鏡像信息、維護者信息蛋勺、鏡像
操作指令和容器啟動時執(zhí)行指令瓦灶。例如:

# This Dockerfile uses the ubuntu image
# VERSION 2 - EDITION 1
# Author: docker_user
# Command format: Instruction [arguments / command] ..
# Base image to use, this must be set as the first line
FROM ubuntu
# Maintainer: docker_user <docker_user at email.com> (@docker_user)
MAINTAINER docker_user docker_user@email.com
# Commands to update the image
RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe" >> /etc/apt/
sources.list
RUN apt-get update && apt-get install -y nginx
RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf
# Commands when creating a new container
CMD /usr/sbin/nginx

其中,一開始必須指明所基于的鏡像名稱抱完,接下來一般是說明維護者信息贼陶。后面則是鏡像操作指令,例如RUN指令巧娱,RUN指令將對鏡像執(zhí)行跟隨的命令碉怔。每運行一條RUN指令,鏡像就添加新的一層禁添,并提交撮胧。最后是CMD指令,用來指定運行容器時的操作命令老翘。

Dockerfile 官方參考

2芹啥、 指令說明

Dockerfile 指令 說明
FROM 指定基礎(chǔ)鏡像,用于后續(xù)的指令構(gòu)建铺峭。
MAINTAINER 指定Dockerfile的作者/維護者墓怀。(已棄用,推薦使用LABEL指令)
LABEL 添加鏡像的元數(shù)據(jù)卫键,使用鍵值對的形式傀履。
RUN 在構(gòu)建過程中在鏡像中執(zhí)行命令。
CMD 指定容器創(chuàng)建時的默認命令莉炉。(可以被覆蓋)
ENTRYPOINT 設置容器創(chuàng)建時的主要命令钓账。(不可被覆蓋)
EXPOSE 聲明容器運行時監(jiān)聽的特定網(wǎng)絡端口碴犬。
ENV 在容器內(nèi)部設置環(huán)境變量。
ADD 將文件官扣、目錄或遠程URL復制到鏡像中翅敌,tar文件會自動解壓。
COPY 將文件或目錄復制到鏡像中惕蹄。
VOLUME 為容器創(chuàng)建掛載點或聲明卷蚯涮。
WORKDIR 設置后續(xù)指令的工作目錄。
USER 指定后續(xù)指令的用戶上下文卖陵。
ARG 定義在構(gòu)建過程中傳遞給構(gòu)建器的變量遭顶,可使用 "docker build" 命令設置。
ONBUILD 當該鏡像被用作另一個構(gòu)建過程的基礎(chǔ)時泪蔫,添加觸發(fā)器棒旗。
STOPSIGNAL 設置發(fā)送給容器以退出的系統(tǒng)調(diào)用信號。
HEALTHCHECK 定義周期性檢查容器健康狀態(tài)的命令撩荣。
SHELL 覆蓋Docker中默認的shell铣揉,用于RUN、CMD和ENTRYPOINT指令餐曹。
  • FROM
    指定所創(chuàng)建鏡像的基礎(chǔ)鏡像逛拱,如果本地不存在,則默認會去Docker Hub下載指定鏡像台猴。
    任何Dockerfile中的第一條非注釋指令必須為FROM指令朽合。并且,如果在同一個Dockerfile中創(chuàng)建多個鏡像饱狂,可以使用多個FROM指令(每個鏡像一次)曹步。
    空鏡像: scratch

  • MAINTAINER
    指定維護者信息,格式為MAINTAINER <name>休讳,已棄用讲婚,推薦使用LABEL指令

LABEL org.opencontainers.image.authors="SvenDowideit@home.org.au"

  • RUN
    運行指定的命令。
    格式為RUN <command>或RUN ["executable"俊柔,"param1"磺樱,"param2"]。注意婆咸,后一個指令會被解析為Json數(shù)組竹捉,因此必須用雙引號。
    前者默認將在shell終端中運行命令尚骄,即/ bin/sh -c块差;后者則使用exec執(zhí)行,不會啟動shell環(huán)境。
    指定使用其他終端類型可以通過第二種方式實現(xiàn)憨闰,例如RUN ["/bin/ bash"状蜗,"-c","echo hello"]鹉动。
    每條RUN指令將在當前鏡像的基礎(chǔ)上執(zhí)行指定命令轧坎,并提交為新的鏡像。當命令較長時可以使用\來換行泽示。例如:
RUN apt-get update \
&& apt-get install -y libsnappy-dev zlib1g-dev libbz2-dev \
&& rm -rf /var/cache/apt
  • CMD
    CMD指令用來指定啟動容器時默認執(zhí)行的命令缸血。它支持三種格式:
    · CMD ["executable","param1"械筛,"param2"]使用 exec執(zhí)行捎泻,是推薦使用的方式;
    · CMD command param1 param2在/bin/sh中執(zhí)行埋哟,提供給需要交互的應用笆豁;
    · CMD ["param1","param2"]提供給 ENTRYPOINT的默認參數(shù)赤赊。
    每個Dockerfile只能有一條CMD命令闯狱。如果指定了多條命令,只有最后一條會被執(zhí)行抛计。
    如果用戶啟動容器時手動指定了運行的命令(作為run的參數(shù))哄孤,則會覆蓋掉CMD指定的命令。
  • LABEL
    LABEL指令用來指定生成鏡像的元數(shù)據(jù)標簽信息爷辱。
LABEL version="1.0"
LABEL description="This text illustrates \ that label-values can span multiple lines."
  • EXPOSE
    聲明鏡像內(nèi)服務所監(jiān)聽的端口。

EXPOSE 22 80 8443

注意朦肘,該指令只是起到聲明作用饭弓,并不會自動完成端口映射。
在啟動容器時需要使用-P媒抠,Docker主機會自動分配一個宿主機的臨時端口轉(zhuǎn)發(fā)到指定的端口弟断;使用-p,則可以具體指定哪個宿主機的本地端口會映射過來趴生。

  • ENV
    指定環(huán)境變量阀趴,在鏡像生成過程中會被后續(xù)RUN指令使用,在鏡像啟動的容器中也會存在
ENV PG_MAJOR 9.3
ENV PG_VERSION 9.3.4
RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/
postgress && …
ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH

指令指定的環(huán)境變量在運行時可以被覆蓋掉苍匆,如docker run --env <key>=<value> built_image刘急。

  • ADD
    該命令將復制指定的<src>路徑下的內(nèi)容到容器中的<dest>路徑下。
    格式為ADD<src><dest>浸踩。
    其中<src>可以是Dockerfile所在目錄的一個相對路徑(文件或目錄)叔汁,也可以是一個URL,還可以是一個tar文件(如果為tar文件,會自動解壓到<dest>路徑下)据块。<dest>可以是鏡像內(nèi)的絕對路徑码邻,或者相對于工作目錄(WORKDIR)的相對路徑。

ADD *.c /code/

  • COPY
    格式為COPY<src><dest>另假。
    復制本地主機的<src>(為Dockerfile所在目錄的相對路徑像屋、文件或目錄)下的內(nèi)容到鏡像中的<dest>下。目標路徑不存在時边篮,會自動創(chuàng)建己莺。
    路徑同樣支持正則格式。
    當使用本地目錄為源目錄時苟耻,推薦使用COPY篇恒。

  • 指定鏡像的默認入口命令,該入口命令會在啟動容器時作為根命令執(zhí)行凶杖,所有傳入值作為該命令的參數(shù)胁艰。
    支持兩種格式:

ENTRYPOINT ["executable", "param1", "param2"](exec調(diào)用執(zhí)行);
ENTRYPOINT command param1 param2(shell中執(zhí)行)智蝠。

此時腾么,CMD指令指定值將作為根命令的參數(shù)。
每個Dockerfile中只能有一個ENTRYPOINT杈湾,當指定多個時解虱,只有最后一個有效。
在運行時漆撞,可以被--entrypoint參數(shù)覆蓋掉殴泰,如docker run --entrypoint。

  • VOLUME
    創(chuàng)建一個數(shù)據(jù)卷掛載點浮驳,格式為VOLUME["/data"]悍汛。
    可以從本地主機或其他容器掛載數(shù)據(jù)卷,一般用來存放數(shù)據(jù)庫和需要保存的數(shù)據(jù)等至会。

  • USER
    指定運行容器時的用戶名或UID离咐,后續(xù)的RUN等指令也會使用指定的用戶身份。
    格式為USER daemon奉件。
    當服務不需要管理員權(quán)限時宵蛀,可以通過該命令指定運行用戶,并且可以在之前創(chuàng)建所需要的用戶县貌。例如:

RUN groupadd -r postgres && useradd -r -g postgres postgres

  • WORKDIR
    為后續(xù)的RUN术陶、CMD和ENTRYPOINT指令配置工作目錄。
    格式為WORKDIR/path/to/workdir煤痕。
    可以使用多個WORKDIR指令瞳别,后續(xù)命令如果參數(shù)是相對路徑征候,則會基于之前命令指定的路徑。例如:
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

則最終路徑為/ a/b/c祟敛。

  • ARG
    指定一些鏡像內(nèi)使用的參數(shù)(例如版本號信息等)疤坝,這些參數(shù)在執(zhí)行docker build命令時才以--build-arg <varname>=<value>格式傳入。
    格式為ARG<name>[=<default value>]馆铁。
    則可以用docker build --build-arg <name>=<value>.來指定參數(shù)值跑揉。
    它與 ENV 作用一致。不過作用域不一樣埠巨。ARG 設置的環(huán)境變量僅對 Dockerfile 內(nèi)有效历谍,也就是說只有 docker build 的過程中有效,構(gòu)建好的鏡像內(nèi)不存在此環(huán)境變量辣垒。

構(gòu)建命令 docker build 中可以用 --build-arg <參數(shù)名>=<值> 來覆蓋望侈。

  • ONBUILD
    配置當所創(chuàng)建的鏡像作為其他鏡像的基礎(chǔ)鏡像時,所執(zhí)行的創(chuàng)建操作指令勋桶。
    格式為ONBUILD[INSTRUCTION]脱衙。
    例如,Dockerfile使用如下的內(nèi)容創(chuàng)建了鏡像 image-A:
[...]
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
[...]

如果基于image-A創(chuàng)建新的鏡像時例驹,新的Dockerfile中使用FROM image-A指定基礎(chǔ)鏡像捐韩,會自動執(zhí)行ONBUILD指令的內(nèi)容,等價于在后面添加了兩條指令:

FROM image-A
#Automatically run the following
ADD . /app/src
RUN /usr/local/bin/python-build --dir /app/src

使用ONBUILD指令的鏡像鹃锈,推薦在標簽中注明荤胁,例如ruby:1.9-onbuild。

  • STOPSIGNAL
    指定所創(chuàng)建鏡像啟動的容器接收退出的信號值屎债。例如:

STOPSIGNAL signal

  • HEALTHCHECK
    配置所啟動容器如何進行健康檢查(如何判斷健康與否)仅政,自Docker1.12開始支持。
    格式有兩種:

HEALTHCHECK [OPTIONS] CMD command:根據(jù)所執(zhí)行命令返回值是否為0來判斷盆驹;

·HEALTHCHECK[OPTIONS]CMD command:根據(jù)所執(zhí)行命令返回值是否為0來判斷圆丹;
·HEALTHCHECK NONE:禁止基礎(chǔ)鏡像中的健康檢查。
OPTION支持:
·--interval=DURATION(默認為:30s):過多久檢查一次召娜;
·--timeout=DURATION(默認為:30s):每次檢查等待結(jié)果的超時运褪;
·--retries=N(默認為:3):如果失敗了惊楼,重試幾次才最終確定失敗玖瘸。

  • SHELL
    指定其他命令使用shell時的默認shell類型。
    默認值為["/bin/sh"檀咙,"-c"]雅倒。

3、創(chuàng)建鏡像

編寫完成Dockerfile之后弧可,可以通過docker build命令來創(chuàng)建鏡像蔑匣。

$ docker build -t test-image:1.1 /tmp/docker_builder/

4、使用.dockerignore文件

可以通過.dockerignore文件(每一行添加一條匹配模式)來讓 Docker忽略匹配模式路徑下的目錄和文件。例如:

# comment
*/temp*
*/*/temp*
tmp?
~*

5裁良、最佳實踐

所謂最佳實踐凿将,實際上是從需求出發(fā),來定制適合自己价脾、高效方便的鏡像牧抵。
首先,要盡量吃透每個指令的含義和執(zhí)行效果侨把,自己多編寫一些簡單的例子進行測試犀变,弄清楚了再撰寫正式的Dockerfile。此外秋柄,Docker Hub官方倉庫中提供了大量的優(yōu)秀鏡像和對應的Dockefile获枝,可以通過閱讀它們來學習如何撰寫高效的Dockerfile。
筆者在應用過程中也總結(jié)了一些實踐經(jīng)驗骇笔。建議讀者在生成鏡像過程中省店,嘗試從如下角度進行思考,完善所生成的鏡像蜘拉。

  • 精簡鏡像用途:盡量讓每個鏡像的用途都比較集中萨西、單一,避免構(gòu)造大而復雜旭旭、多功能的鏡像谎脯;
  • 選用合適的基礎(chǔ)鏡像:過大的基礎(chǔ)鏡像會造成生成臃腫的鏡像,一般推薦較為小巧的debian鏡像持寄;
  • 提供足夠清晰的命令注釋和維護者信息:Dockerfile也是一種代碼源梭,需要考慮方便后續(xù)擴展和他人使用;
  • 正確使用版本號:使用明確的版本號信息稍味,如1.0废麻,2.0,而非latest模庐,將避免內(nèi)容不一致可能引發(fā)的慘案烛愧;
  • 減少鏡像層數(shù):如果希望所生成鏡像的層數(shù)盡量少,則要盡量合并指令掂碱,例如多個RUN指令可以合并為一條怜姿;
  • 及時刪除臨時文件和緩存文件:特別是在執(zhí)行apt-get指令后,/var/cache/apt下面會緩存一些安裝包疼燥;
  • ·提高生成?度:如合理使用緩存沧卢,減少內(nèi)容目錄下的文件,或使用.dockerignore文件指定等醉者;
  • 調(diào)整合理的指令順序:在開啟緩存的情況下但狭,內(nèi)容不變的指令盡量放在前面披诗,這樣可以盡量復用;
  • 減少外部源的干擾:如果確實要從外部引入數(shù)據(jù)立磁,需要指定持久的地址呈队,并帶有版本信息,讓他人可以重復而不出錯唱歧。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末掂咒,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子迈喉,更是在濱河造成了極大的恐慌绍刮,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件挨摸,死亡現(xiàn)場離奇詭異孩革,居然都是意外死亡,警方通過查閱死者的電腦和手機得运,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門膝蜈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人熔掺,你說我怎么就攤上這事饱搏。” “怎么了置逻?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵推沸,是天一觀的道長。 經(jīng)常有香客問我券坞,道長鬓催,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任恨锚,我火速辦了婚禮宇驾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘猴伶。我一直安慰自己课舍,他們只是感情好,可當我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布他挎。 她就那樣靜靜地躺著筝尾,像睡著了一般。 火紅的嫁衣襯著肌膚如雪雇盖。 梳的紋絲不亂的頭發(fā)上忿等,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天栖忠,我揣著相機與錄音崔挖,去河邊找鬼贸街。 笑死,一個胖子當著我的面吹牛狸相,可吹牛的內(nèi)容都是我干的薛匪。 我是一名探鬼主播,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼脓鹃,長吁一口氣:“原來是場噩夢啊……” “哼逸尖!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起瘸右,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤娇跟,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后太颤,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體苞俘,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年龄章,在試婚紗的時候發(fā)現(xiàn)自己被綠了吃谣。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡做裙,死狀恐怖岗憋,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情锚贱,我是刑警寧澤仔戈,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站拧廊,受9級特大地震影響杂穷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜卦绣,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一耐量、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧滤港,春花似錦廊蜒、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至添履,卻和暖如春屁倔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背暮胧。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工锐借, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留问麸,地道東北人。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓钞翔,卻偏偏與公主長得像严卖,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子布轿,可洞房花燭夜當晚...
    茶點故事閱讀 43,452評論 2 348

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